rasputin 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -14,6 +14,7 @@ And it also provides some unnoficial packages :
14
14
  * sproutcore-jui (jQuery UI wrappers for sc 2.0)
15
15
  * sproutcore-ajax (backport form sc 1.x API but using jQuery $.ajax)
16
16
  * sproutcore-i18n (integration with i18n-js gem)
17
+ * sproutcore-bricks (some useful bricks extracted form my projects)
17
18
 
18
19
  Rasputin also provide sprockets engine for handlebars templates. Any template in your
19
20
  javascript assets folder with extention handlebars will be availabel in sproutcore.
@@ -28,3 +29,5 @@ Changelog :
28
29
  0.6.0 :
29
30
  - update to lates sproutcore 2 (beta3)
30
31
  - lots of fixes for sproutcore-jui
32
+ 0.7.0 :
33
+ - add sproutcore-bricks
@@ -1,3 +1,3 @@
1
1
  module Rasputin
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -0,0 +1,68 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // current_user.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.CurrentUser = SC.Object.extend({
11
+ username: '',
12
+ password: '',
13
+ rememberMe: true,
14
+
15
+ url: '/authenticate',
16
+ authenticateMethod: 'HEAD',
17
+
18
+ isLoggedIn: false,
19
+ isLoggingIn: false,
20
+
21
+ didLoggedIn: SC.K,
22
+ didLoggedOut: SC.K,
23
+ loginSuccess: SC.K,
24
+ loginError: SC.K,
25
+
26
+ setCredentials: SC.K,
27
+ resetCredentials: SC.K,
28
+
29
+ login: function() {
30
+ if (this.get('isLoggedIn')) {return;}
31
+ this.set('isLoggingIn', true);
32
+ var username = this.get('username'),
33
+ password = this.get('password');
34
+ if (!SC.empty(username) && !SC.empty(password)) {
35
+ this.setCredentials(username, password);
36
+ }
37
+ var method = "%@Url".fmt(this.get('authenticateMethod').toLowerCase());
38
+ SC.Request[method](this.get('url')).json()
39
+ .notify(this, 'loginComplete')
40
+ .send();
41
+ },
42
+
43
+ logout: function() {
44
+ if (!this.get('isLoggedIn')) {return;}
45
+ this.setProperties({'username': '', 'password': ''});
46
+ this.resetCredentials();
47
+ this.set('isLoggedIn', false);
48
+ this.didLoggedOut();
49
+ },
50
+
51
+ /*
52
+ @private
53
+ */
54
+ loginComplete: function(response) {
55
+ this.set('isLoggingIn', false);
56
+ if (SC.ok(response)) {
57
+ this.set('isLoggedIn', true);
58
+ this.loginSuccess(response);
59
+ this.didLoggedIn();
60
+ this.setProperties({'username': '', 'password': ''});
61
+ } else {
62
+ this.set('isLoggedIn', false);
63
+ this.set('password', '');
64
+ this.resetCredentials();
65
+ this.loginError(response);
66
+ }
67
+ }
68
+ });
@@ -0,0 +1,23 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // images_error.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.ImagesErrorSupport = SC.Mixin.create({
11
+ didInsertElement: function() {
12
+ this._super();
13
+ var img = this.$('img[data-rescue-errors]'), self = this;
14
+ img.hide().error(function() {
15
+ if (self.imageLoadError(img)) {
16
+ img.show();
17
+ }
18
+ }).load(function() {
19
+ img.show();
20
+ });
21
+ },
22
+ imageLoadError: SC.K
23
+ });
@@ -0,0 +1,50 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // layout_manager.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.layoutManager = SC.Object.create({
11
+ windowWidth: 0,
12
+ windowHeight: 0,
13
+
14
+ init: function() {
15
+ this._windowSize();
16
+ this._window.resize(SC.$.proxy(this, '_onResize'));
17
+ },
18
+ registerLayout: function(view) {
19
+ this._managedViews.pushObject(view);
20
+ this._callApplyLayout(view);
21
+ },
22
+
23
+ _managedViews: [],
24
+ _window: SC.$(window),
25
+
26
+ _onResize: function() {
27
+ this._windowSize();
28
+ this._managedViews.forEach(this._callApplyLayout, this);
29
+ },
30
+ _windowSize: function() {
31
+ this.set('windowWidth', this._window.width());
32
+ this.set('windowHeight', this._window.height());
33
+ },
34
+ _callApplyLayout: function(view) {
35
+ if (view && view.get('state') === 'inDOM'
36
+ && view.get('hasLayout') === true
37
+ && typeof view.applyLayout === 'function') {
38
+ view.applyLayout(this.windowWidth, this.windowHeight);
39
+ }
40
+ }
41
+ });
42
+
43
+ SB.ManagedLayoutSupport = SC.Mixin.create({
44
+ hasLayout: true,
45
+
46
+ didInsertElement: function() {
47
+ this._super();
48
+ SB.layoutManager.registerLayout(this);
49
+ }
50
+ });
@@ -0,0 +1,174 @@
1
+ // ==========================================================================
2
+ // Project: Todos.LocalStorage
3
+ // Copyright: ©2011 My Company, Inc.
4
+ // ==========================================================================
5
+ /*globals Todos */
6
+
7
+ /** @class
8
+
9
+ This data source serves as an adapter between SproutCore's data store and the
10
+ browser's local storage.
11
+
12
+ @extends SC.DataSource
13
+ */
14
+ SB = this.SB || {};
15
+
16
+ (function() {
17
+ var supportsLocalStorage = false;
18
+ // HTML5 localStorage detection from http://diveintohtml5.org/storage.html
19
+ try {
20
+ supportsLocalStorage = ('localStorage' in window && window['localStorage'] !== null);
21
+ } catch (e) { }
22
+
23
+ if (!supportsLocalStorage) {
24
+ var warnMethod = function() {
25
+ console.log('Unable to use local storage data source because your browser does not support local storage.');
26
+ return false;
27
+ };
28
+
29
+ SB.LocalStorageDataSource = SC.DataSource.extend({
30
+ fetch: warnMethod,
31
+ retrieveRecord: warnMethod,
32
+ createRecord: warnMethod,
33
+ updateRecord: warnMethod,
34
+ destroyRecord: warnMethod
35
+ });
36
+
37
+ return;
38
+ }
39
+
40
+ SB.LocalStorageDataSource = SC.DataSource.extend(
41
+ /** @scope SC.LocalStorage.prototype */ {
42
+ /**
43
+ The string to prefix to the key used to store the data in the browser's
44
+ localStorage.
45
+
46
+ @type String
47
+ @default 'sproutcore-local-storage'
48
+ */
49
+ storagePrefix: 'sproutcore.local.storage.',
50
+
51
+ // ..........................................................
52
+ // QUERY SUPPORT
53
+ //
54
+
55
+ fetch: function(store, query) {
56
+ var recordType = query.get('recordType');
57
+ var key = this._keyForRecordType(recordType);
58
+ var data = localStorage.getItem(key);
59
+
60
+ if (data) {
61
+ data = JSON.parse(data);
62
+ } else {
63
+ data = {};
64
+ }
65
+
66
+ data.__guid = data.__guid || 0;
67
+
68
+ var dataByRecordType = this.get('dataByRecordType') || {};
69
+ dataByRecordType[key] = data;
70
+
71
+ this.set('dataByRecordType', dataByRecordType);
72
+
73
+ var records = [];
74
+ for (key in data) {
75
+ if (data.hasOwnProperty(key) && key !== '__guid') {
76
+ records.push(data[key]);
77
+ }
78
+ }
79
+
80
+ store.loadRecords(recordType, records);
81
+ return true; // return true if you handled the query
82
+ },
83
+
84
+ _keyForRecordType: function(recordType) {
85
+ var recordTypeKey = recordType.localStorageKey;
86
+ return this.get('storagePrefix')+recordTypeKey;
87
+ },
88
+
89
+ // ..........................................................
90
+ // RECORD SUPPORT
91
+ //
92
+
93
+ retrieveRecord: function(store, storeKey, guid) {
94
+ var recordType = store.recordTypeFor(storeKey);
95
+ var data = this._dataForRecordType(recordType);
96
+
97
+ store.dataSourceDidComplete(storeKey, data[guid]);
98
+
99
+ return true; // return true if you handled the storeKey
100
+ },
101
+
102
+ createRecord: function(store, storeKey) {
103
+ var guid = store.idFor(storeKey);
104
+ var recordType = store.recordTypeFor(storeKey);
105
+ var data = store.readDataHash(storeKey);
106
+
107
+ if (guid === undefined || guid === null) {
108
+ guid = this._generateGuid(recordType);
109
+ }
110
+
111
+ this._writeRecord(data, recordType, guid);
112
+ this._writeDataToLocalStorage(recordType);
113
+
114
+ store.dataSourceDidComplete(storeKey, null, guid);
115
+
116
+ return true; // return true if you handled the storeKey
117
+ },
118
+
119
+ updateRecord: function(store, storeKey) {
120
+ var guid = store.idFor(storeKey);
121
+ var recordType = store.recordTypeFor(storeKey);
122
+ var data = store.readDataHash(storeKey);
123
+
124
+ this._writeRecord(data, recordType, guid);
125
+ this._writeDataToLocalStorage(recordType);
126
+
127
+ store.dataSourceDidComplete(storeKey, null, guid);
128
+ return true; // return true if you handled the storeKey
129
+ },
130
+
131
+ _writeRecord: function(hash, recordType, guid) {
132
+ var data = this._dataForRecordType(recordType);
133
+ var primaryKey = recordType.prototype.primaryKey;
134
+
135
+
136
+ data[guid] = hash;
137
+ hash[primaryKey] = guid;
138
+ },
139
+
140
+ destroyRecord: function(store, storeKey) {
141
+ var guid = store.idFor(storeKey);
142
+ var recordType = store.recordTypeFor(storeKey);
143
+ var data = this._dataForRecordType(recordType);
144
+
145
+ delete data[guid];
146
+
147
+ this._writeDataToLocalStorage(recordType);
148
+
149
+ store.dataSourceDidDestroy(storeKey);
150
+
151
+ return true; // return true if you handled the storeKey
152
+ },
153
+
154
+ _writeDataToLocalStorage: function(recordType) {
155
+ var dataByRecordType = this.get('dataByRecordType');
156
+ var key = this._keyForRecordType(recordType);
157
+
158
+ localStorage[key] = JSON.stringify(dataByRecordType[key]);
159
+ },
160
+
161
+ _dataForRecordType: function(recordType) {
162
+ var key = this._keyForRecordType(recordType);
163
+ var dataByRecordType = this.get('dataByRecordType');
164
+
165
+ return dataByRecordType[key];
166
+ },
167
+
168
+ _generateGuid: function(recordType) {
169
+ var data = this._dataForRecordType(recordType);
170
+
171
+ return ++data.__guid;
172
+ }
173
+ }) ;
174
+ })();
@@ -0,0 +1,63 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // paginated_array.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.PaginatedArray = SC.ArrayProxy.extend({
11
+ content: [],
12
+
13
+ limit: 100,
14
+ offset: 0,
15
+ total: 0,
16
+
17
+ isLoading: false,
18
+ didRequireRange: SC.K,
19
+
20
+ reset: function() {
21
+ this.set('offset', 0);
22
+ this.set('total', 0);
23
+ this.set('content', []);
24
+ this._didRequireRange(this.limit, 0);
25
+ },
26
+
27
+ reload: function() {
28
+ this._didRequireRange(this.limit, this.offset);
29
+ },
30
+
31
+ _didRequireRange: function(limit, offset) {
32
+ this.set('isLoading', true);
33
+ this.didRequireRange(limit, offset);
34
+ },
35
+
36
+ rangeDidLoaded: function(total, content) {
37
+ this.set('total', total);
38
+ this.set('content', content);
39
+ this.set('isLoading', false);
40
+ },
41
+
42
+ nextPage: function() {
43
+ if (this.get('hasNextPage')) {
44
+ this.incrementProperty('offset');
45
+ this._didRequireRange(this.limit, this.offset);
46
+ }
47
+ },
48
+
49
+ previousPage: function() {
50
+ if (this.get('hasPreviousPage')) {
51
+ this.decrementProperty('offset');
52
+ this._didRequireRange(this.limit, this.offset);
53
+ }
54
+ },
55
+
56
+ hasNextPage: function() {
57
+ return (this.offset+1)*this.limit < this.total;
58
+ }.property('offset', 'limit', 'total').cacheable(),
59
+
60
+ hasPreviousPage: function() {
61
+ return this.offset > 0;
62
+ }.property('offset').cacheable()
63
+ });
@@ -0,0 +1,22 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // pagination_buton.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.PreviousButton = JUI.Button.extend({
11
+ label: "Previous",
12
+ action: 'previousPage',
13
+ isVisibleBinding: 'targetObject.hasPreviousPage',
14
+ disabledBinding: 'targetObject.isLoading'
15
+ });
16
+
17
+ SB.NextButton = JUI.Button.extend({
18
+ label: "Next",
19
+ action: 'nextPage',
20
+ isVisibleBinding: 'targetObject.hasNextPage',
21
+ disabledBinding: 'targetObject.isLoading'
22
+ });
@@ -0,0 +1,53 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // pane_view.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.PaneView = SC.View.extend(SB.ToggleViewSupport, {
11
+ templateNamePrefix: null,
12
+ rootElement: '[role="application"]',
13
+ classNames: ['pane'],
14
+ classNameBindings: ['paneClassName'],
15
+
16
+ templateName: function() {
17
+ var prefix = this.get('templateNamePrefix');
18
+ if (prefix) {
19
+ return prefix + '_' + this.get('name');
20
+ }
21
+ return this.get('name');
22
+ }.property('templateNamePrefix', 'name').cacheable(),
23
+
24
+ paneClassName: function() {
25
+ return this.get('name') + '-pane';
26
+ }.property('name').cacheable(),
27
+
28
+ append: function() {
29
+ var currentPane = SB.PaneView.currentPane;
30
+ if (currentPane && currentPane.state === 'inDOM') {
31
+ currentPane.hide();
32
+ }
33
+ if (this.state === 'inDOM') {
34
+ this.show();
35
+ } else {
36
+ this.appendTo(this.get('rootElement'));
37
+ }
38
+ SB.PaneView.currentPane = this;
39
+ }
40
+ });
41
+
42
+ SC.Application.reopen({
43
+ paneViewClass: SB.PaneView,
44
+
45
+ createPanes: function(panes) {
46
+ var paneViewClass = this.get('paneViewClass');
47
+ (panes || []).forEach(function(paneName) {
48
+ this["%@PaneView".fmt(paneName)] = paneViewClass.create({
49
+ name: paneName.toLowerCase()
50
+ });
51
+ }, this);
52
+ }
53
+ });
@@ -0,0 +1,119 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // rest_data_source.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.RestDataSource = SC.DataSource.extend({
11
+
12
+ storagePrefix: null,
13
+
14
+ resourceURL: function(recordType, store, storeKey) {
15
+ var id, resourceName = recordType.resourceName,
16
+ prefix = this.get('storagePrefix');
17
+ if (!resourceName) {
18
+ throw SC.Error.create("You have to define resourceName on %@ ...".fmt(recordType));
19
+ }
20
+ if (storeKey) {
21
+ id = store.idFor(storeKey);
22
+ }
23
+ if (prefix) {
24
+ resourceName = '%@/%@'.fmt(prefix, resourceName);
25
+ }
26
+ if (id) {
27
+ return '/%@/%@'.fmt(resourceName, id);
28
+ }
29
+ return '/%@'.fmt(resourceName);
30
+ },
31
+
32
+ // fetch
33
+
34
+ fetch: function(store, query) {
35
+ var url = this.resourceURL(query.get('recordType'), store);
36
+ SC.Request.getUrl(url).json()
37
+ .notify(this, 'fetchDidComplete', store, query)
38
+ .send();
39
+ return true;
40
+ },
41
+
42
+ fetchDidComplete: function(response, store, query) {
43
+ if (SC.ok(response)) {
44
+ var data = response.get('body');
45
+ store.loadRecords(query.get('recordType'), data);
46
+ store.dataSourceDidFetchQuery(query);
47
+ } else {
48
+ store.dataSourceDidErrorQuery(query, response);
49
+ }
50
+ },
51
+
52
+ // retrieve
53
+
54
+ retrieveRecord: function(store, storeKey, id) {
55
+ var url = this.resourceURL(store.recordTypeFor(storeKey), store, storeKey);
56
+ SC.Request.getUrl(url).json()
57
+ .notify(this, 'retrieveRecordDidComplete', store, storeKey)
58
+ .send();
59
+ return true;
60
+ },
61
+
62
+ retrieveRecordDidComplete: function(response, store, storeKey) {
63
+ if (SC.ok(response)) {
64
+ var data = response.get('body');
65
+ store.dataSourceDidComplete(storeKey, data);
66
+ } else {
67
+ store.dataSourceDidError(storeKey, response);
68
+ }
69
+ },
70
+
71
+ // create / update
72
+
73
+ createRecord: function(store, storeKey) {
74
+ return this._createOrUpdateRecord(store, storeKey);
75
+ },
76
+
77
+ updateRecord: function(store, storeKey) {
78
+ return this._createOrUpdateRecord(store, storeKey, true);
79
+ },
80
+
81
+ _createOrUpdateRecord: function(store, storeKey, update) {
82
+ var url = this.resourceURL(store.recordTypeFor(storeKey), store, storeKey);
83
+ SC.Request[update ? 'putUrl' : 'postUrl'](url).json()
84
+ .notify(this, 'writeRecordDidComplete', store, storeKey)
85
+ .send(store.readDataHash(storeKey));
86
+ return true;
87
+ },
88
+
89
+ writeRecordDidComplete: function(response, store, storeKey) {
90
+ if (SC.ok(response)) {
91
+ var data = response.get('body');
92
+ if (store.idFor(storeKey)) {
93
+ store.dataSourceDidComplete(storeKey, data);
94
+ } else {
95
+ store.dataSourceDidComplete(storeKey, data, data.id);
96
+ }
97
+ } else {
98
+ store.dataSourceDidError(storeKey, response);
99
+ }
100
+ },
101
+
102
+ // destroy
103
+
104
+ destroyRecord: function(store, storeKey) {
105
+ var url = this.resourceURL(store.recordTypeFor(storeKey), store, storeKey);
106
+ SC.Request.deleteUrl(url).json()
107
+ .notify(this, 'destroyRecordDidComplete', store, storeKey)
108
+ .send();
109
+ return true;
110
+ },
111
+
112
+ destroyRecordDidComplete: function(response, store, storeKey) {
113
+ if (SC.ok(response)) {
114
+ store.dataSourceDidDestroy(storeKey);
115
+ } else {
116
+ store.dataSourceDidError(storeKey, response);
117
+ }
118
+ }
119
+ });
@@ -0,0 +1,28 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore Bricks
3
+ // Copyright: ©2011 Paul Chavard
4
+ // Author : Paul Chavard
5
+ //
6
+ // toggle_view.js
7
+ // ==========================================================================
8
+ SB = this.SB || {};
9
+
10
+ SB.ToggleViewSupport = SC.Mixin.create({
11
+ toggleMethod: 'toggle',
12
+
13
+ _isVisibleDidChange: function() {
14
+ var method = this.$()[this.get('toggleMethod')];
15
+ if (!method) { method = 'toggle'; }
16
+ method.call(this.$(), this.get('isVisible'));
17
+ }.observes('isVisible'),
18
+
19
+ show: function() {
20
+ this.set('isVisible', true);
21
+ },
22
+ hide: function() {
23
+ this.set('isVisible', false);
24
+ },
25
+ toggle: function() {
26
+ this.toggleProperty('isVisible');
27
+ }
28
+ });
@@ -257,7 +257,7 @@ var get = SC.get;
257
257
  */
258
258
  JUI.Button = SC.Button.extend(JUI.Widget, {
259
259
  uiType: 'button',
260
- uiOptions: ['label', '_icons'],
260
+ uiOptions: ['label'],
261
261
 
262
262
  isActiveBinding: SC.Binding.oneWay('.disabled'),
263
263
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rasputin
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.6.1
5
+ version: 0.7.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Chavard
@@ -65,13 +65,21 @@ files:
65
65
  - lib/rasputin/handlebars_template.rb
66
66
  - lib/rasputin/version.rb
67
67
  - rasputin.gemspec
68
+ - vendor/assets/javascripts/bricks/current_user.js
69
+ - vendor/assets/javascripts/bricks/images_error.js
70
+ - vendor/assets/javascripts/bricks/layout_manager.js
71
+ - vendor/assets/javascripts/bricks/local_storage_data_source.js
72
+ - vendor/assets/javascripts/bricks/paginated_array.js
73
+ - vendor/assets/javascripts/bricks/pagination_button.js
74
+ - vendor/assets/javascripts/bricks/pane_view.js
75
+ - vendor/assets/javascripts/bricks/rest_data_source.js
76
+ - vendor/assets/javascripts/bricks/toggle_view.js
68
77
  - vendor/assets/javascripts/jquery-ui.js
69
78
  - vendor/assets/javascripts/sproutcore-ajax.js
70
79
  - vendor/assets/javascripts/sproutcore-datastore.js
71
80
  - vendor/assets/javascripts/sproutcore-i18n.js
72
81
  - vendor/assets/javascripts/sproutcore-jui.js
73
82
  - vendor/assets/javascripts/sproutcore-statechart.js
74
- - vendor/assets/javascripts/sproutcore-throbber.js
75
83
  - vendor/assets/javascripts/sproutcore.js
76
84
  - vendor/assets/stylesheets/aristo.css
77
85
  - vendor/assets/stylesheets/jquery-ui.css
@@ -1,258 +0,0 @@
1
-
2
- (function(exports) {
3
- /*!
4
- * jQuery UI Throbber
5
- *
6
- * Copyright (c) 2011 Paul Chavard
7
- * Licensed under the MIT license
8
- *
9
- * Author: Paul Chavard [paul at chavard dot net]
10
- * Version: 0.5.0
11
- *
12
- * Credits: Felix Gnass [fgnass at neteye dot de]
13
- *
14
- */
15
-
16
- (function($, undefined) {
17
-
18
- $.widget('ui.throbber', {
19
- options: {
20
- segments: 12,
21
- space: 3,
22
- length: 7,
23
- width: 4,
24
- speed: 1.2,
25
- align: 'center',
26
- valign: 'center',
27
- padding: 4,
28
- autoStart: false,
29
- outside: true
30
- },
31
-
32
- _create: function() {
33
- this.options = $.extend({color: this.element.css('color')}, this.options);
34
- this._prepare();
35
- if (this.options.autoStart) {
36
- this._activate();
37
- }
38
- },
39
-
40
- _setOption: function(key, value) {
41
- this.options[key] = value;
42
-
43
- if (key === 'disabled') {
44
- if (this.throbber) {
45
- clearInterval(this.interval);
46
- this.throbber.remove();
47
- }
48
- if (value === false) {
49
- this._activate();
50
- }
51
- }
52
-
53
- return this;
54
- },
55
-
56
- _activate: function() {
57
- var options = this.options;
58
- this.throbber = this._render().css('position', 'absolute').prependTo(options.outside ? 'body' : this.element);
59
- var h = this.element.outerHeight() - this.throbber.height();
60
- var w = this.element.outerWidth() - this.throbber.width();
61
- var margin = {
62
- top: options.valign == 'top' ? options.padding : options.valign == 'bottom' ? h - options.padding : Math.floor(h / 2),
63
- left: options.align == 'left' ? options.padding : options.align == 'right' ? w - options.padding : Math.floor(w / 2)
64
- };
65
- var offset = this.element.offset();
66
- if (options.outside) {
67
- this.throbber.css({top: offset.top + 'px', left: offset.left + 'px'});
68
- } else {
69
- margin.top -= this.throbber.offset().top - offset.top;
70
- margin.left -= this.throbber.offset().left - offset.left;
71
- }
72
- this.throbber.css({marginTop: margin.top + 'px', marginLeft: margin.left + 'px'});
73
- this._animate(options.segments, Math.round(10 / options.speed) / 10);
74
- },
75
-
76
- _prepare: function() {
77
- if ($.ui.throbber.renderMethod) {
78
- this.renderMethod = $.ui.throbber.renderMethod;
79
- this.animateMethod = $.ui.throbber.animateMethod;
80
- return;
81
- }
82
- if (document.createElementNS && document.createElementNS( "http://www.w3.org/2000/svg", "svg").createSVGRect) {
83
- $.ui.throbber.renderMethod = 'SVG';
84
- if (document.createElement('div').style.WebkitAnimationName !== undefined) {
85
- $.ui.throbber.animateMethod = 'CSS';
86
- } else {
87
- $.ui.throbber.animateMethod = 'SVG';
88
- }
89
- } else if (this._prepareVML()) {
90
- $.ui.throbber.renderMethod = $.ui.throbber.animateMethod = 'VML';
91
- } else {
92
- $.ui.throbber.renderMethod = $.ui.throbber.animateMethod = 'DOM';
93
- }
94
- this.renderMethod = $.ui.throbber.renderMethod;
95
- this.animateMethod = $.ui.throbber.animateMethod;
96
- },
97
-
98
- _prepareVML: function() {
99
- var s = $('<shape>').css('behavior', 'url(#default#VML)');
100
- var ok = false;
101
- $('body').append(s);
102
- if (s.get(0).adj) {
103
- // VML support detected. Insert CSS rules for group, shape and stroke.
104
- var sheet = document.createStyleSheet();
105
- $.each(['group', 'shape', 'stroke'], function() {
106
- sheet.addRule(this, "behavior:url(#default#VML);");
107
- });
108
- ok = true;
109
- }
110
- $(s).remove();
111
- return ok;
112
- },
113
-
114
- _getOpacity: function(i) {
115
- var steps = this.options.steps || this.options.segments-1;
116
- var end = this.options.opacity !== undefined ? this.options.opacity : 1/steps;
117
- return 1 - Math.min(i, steps) * (1 - end) / steps;
118
- },
119
-
120
- _render: function() {
121
- return this['_render'+this.renderMethod]();
122
- },
123
-
124
- _renderDOM: function() {
125
- return $('<div>').addClass('ui-throbber');
126
- },
127
-
128
- _renderSVG: function() {
129
- var o = this.options;
130
- var innerRadius = o.width*2 + o.space;
131
- var r = (innerRadius + o.length + Math.ceil(o.width / 2) + 1);
132
-
133
- var el = svg().width(r*2).height(r*2);
134
-
135
- var g = svg('g', {
136
- 'stroke-width': o.width,
137
- 'stroke-linecap': 'round',
138
- stroke: o.color
139
- }).appendTo(svg('g', {transform: 'translate('+ r +','+ r +')'}).appendTo(el));
140
-
141
- for (var i = 0; i < o.segments; i++) {
142
- g.append(svg('line', {
143
- x1: 0,
144
- y1: innerRadius,
145
- x2: 0,
146
- y2: innerRadius + o.length,
147
- transform: 'rotate(' + (360 / o.segments * i) + ', 0, 0)',
148
- opacity: this._getOpacity(i)
149
- }));
150
- }
151
- return $('<div>').append(el).width(2*r).height(2*r);
152
- },
153
-
154
- _renderVML: function() {
155
- var o = this.options;
156
- var innerRadius = o.width*2 + o.space;
157
- var r = (innerRadius + o.length + Math.ceil(o.width / 2) + 1);
158
- var s = r*2;
159
- var c = -Math.ceil(s/2);
160
-
161
- var el = $('<group>', {coordsize: s + ' ' + s, coordorigin: c + ' ' + c}).css({top: c, left: c, width: s, height: s});
162
- for (var i = 0; i < o.segments; i++) {
163
- el.append($('<shape>', {path: 'm ' + innerRadius + ',0 l ' + (innerRadius + o.length) + ',0'}).css({
164
- width: s,
165
- height: s,
166
- rotation: (360 / o.segments * i) + 'deg'
167
- }).append($('<stroke>', {color: o.color, weight: o.width + 'px', endcap: 'round', opacity: this._getOpacity(i)})));
168
- }
169
- return $('<group>', {coordsize: s + ' ' + s}).css({width: s, height: s, overflow: 'hidden'}).append(el);
170
- },
171
-
172
- _animate: function(steps, duration) {
173
- this['_animate'+this.animateMethod](steps, duration);
174
- },
175
-
176
- _animateCSS: function(steps, duration) {
177
- if (!animations[steps]) {
178
- var name = 'spin' + steps;
179
- var rule = '@-webkit-keyframes '+ name +' {';
180
- for (var i=0; i < steps; i++) {
181
- var p1 = Math.round(100000 / steps * i) / 1000;
182
- var p2 = Math.round(100000 / steps * (i+1) - 1) / 1000;
183
- var value = '% { -webkit-transform:rotate(' + Math.round(360 / steps * i) + 'deg); }\n';
184
- rule += p1 + value + p2 + value;
185
- }
186
- rule += '100% { -webkit-transform:rotate(100deg); }\n}';
187
- document.styleSheets[0].insertRule(rule);
188
- animations[steps] = name;
189
- }
190
- this.throbber.css('-webkit-animation', animations[steps] + ' ' + duration +'s linear infinite');
191
- },
192
-
193
- _animateSVG: function(steps, duration) {
194
- var rotation = 0;
195
- var g = this.throbber.find('g g').get(0);
196
- this.interval = setInterval(function() {
197
- g.setAttributeNS(null, 'transform', 'rotate(' + (++rotation % steps * (360 / steps)) + ')');
198
- }, duration * 1000 / steps);
199
- },
200
-
201
- _animateVML: function(steps, duration) {
202
- var rotation = 0;
203
- var g = this.throbber.get(0);
204
- this.interval = setInterval(function() {
205
- g.style.rotation = ++rotation % steps * (360 / steps);
206
- }, duration * 1000 / steps);
207
- },
208
-
209
- _animateDOM: function(steps, duration) {}
210
-
211
- });
212
-
213
- /**
214
- * Utility function to create elements in the SVG namespace.
215
- */
216
- function svg(tag, attr) {
217
- var el = document.createElementNS("http://www.w3.org/2000/svg", tag || 'svg');
218
- if (attr) {
219
- $.each(attr, function(k, v) {
220
- el.setAttributeNS(null, k, v);
221
- });
222
- }
223
- return $(el);
224
- }
225
-
226
- var animations = {};
227
-
228
- })(jQuery);
229
-
230
- })({});
231
-
232
-
233
- (function(exports) {
234
-
235
- /*
236
- * JUI.Throbber
237
- */
238
-
239
- JUI.Throbber = SC.View.extend(JUI.Widget, {
240
- uiType: 'throbber',
241
- uiOptions: ['segments', 'space', 'length', 'width',
242
- 'speed', 'align', 'valign', 'padding', 'autoStart', 'outside']
243
- });
244
-
245
- })({});
246
-
247
-
248
- (function(exports) {
249
- // ==========================================================================
250
- // Project: SproutCore DataStore
251
- // Copyright: ©2006-2011 Strobe Inc. and contributors.
252
- // Portions ©2008-2011 Apple Inc. All rights reserved.
253
- // License: Licensed under MIT license (see license.js)
254
- // ==========================================================================
255
-
256
-
257
-
258
- })({});