sproutcore 0.9.9 → 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +9 -0
- data/Manifest.txt +32 -32
- data/app_generators/sproutcore/sproutcore_generator.rb +2 -0
- data/app_generators/sproutcore/templates/README +5 -5
- data/bin/sc-gen +1 -1
- data/bin/sproutcore +1 -0
- data/frameworks/sproutcore/Core.js +26 -11
- data/frameworks/sproutcore/HISTORY +6 -0
- data/frameworks/sproutcore/controllers/array.js +1 -1
- data/frameworks/sproutcore/drag/drag.js +2 -2
- data/frameworks/sproutcore/english.lproj/panes.css +1 -1
- data/frameworks/sproutcore/english.lproj/theme.css +4 -4
- data/frameworks/sproutcore/foundation/binding.js +2 -1
- data/frameworks/sproutcore/foundation/input_manager.js +9 -8
- data/frameworks/sproutcore/foundation/path_module.js +1 -1
- data/frameworks/sproutcore/lib/core_views.rb +3 -1
- data/frameworks/sproutcore/lib/index.rhtml +2 -2
- data/frameworks/sproutcore/lib/menu_views.rb +6 -1
- data/frameworks/sproutcore/mixins/observable.js +119 -17
- data/frameworks/sproutcore/mixins/scrollable.js +5 -3
- data/frameworks/sproutcore/tests/views/view/innerFrame.rhtml +3 -1
- data/frameworks/sproutcore/views/button/button.js +15 -0
- data/frameworks/sproutcore/views/field/textarea_field.js +8 -0
- data/frameworks/sproutcore/views/form.js +39 -33
- data/frameworks/sproutcore/views/popup_menu.js +7 -11
- data/frameworks/sproutcore/views/view.js +31 -7
- data/lib/sproutcore/bundle.rb +44 -11
- data/lib/sproutcore/library.rb +5 -5
- data/lib/sproutcore/merb/bundle_controller.rb +7 -3
- data/lib/sproutcore/version.rb +1 -1
- data/{generators → sc_generators}/client/README +1 -1
- data/{generators → sc_generators}/client/USAGE +0 -0
- data/{generators → sc_generators}/client/client_generator.rb +0 -0
- data/{generators → sc_generators}/client/templates/core.js +0 -0
- data/{generators → sc_generators}/client/templates/english.lproj/body.css +0 -0
- data/{generators → sc_generators}/client/templates/english.lproj/body.rhtml +0 -0
- data/{generators → sc_generators}/client/templates/english.lproj/strings.js +0 -0
- data/{generators → sc_generators}/client/templates/main.js +0 -0
- data/{generators → sc_generators}/controller/USAGE +0 -0
- data/{generators → sc_generators}/controller/controller_generator.rb +0 -0
- data/{generators → sc_generators}/controller/templates/controller.js +0 -0
- data/{generators → sc_generators}/controller/templates/test.rhtml +0 -0
- data/{generators → sc_generators}/framework/README +1 -1
- data/{generators → sc_generators}/framework/USAGE +0 -0
- data/{generators → sc_generators}/framework/framework_generator.rb +0 -0
- data/{generators → sc_generators}/framework/templates/core.js +0 -0
- data/{generators → sc_generators}/framework/templates/english.lproj/strings.js +0 -0
- data/{generators → sc_generators}/language/USAGE +0 -0
- data/{generators → sc_generators}/language/language_generator.rb +0 -0
- data/{generators → sc_generators}/language/templates/strings.js +0 -0
- data/{generators → sc_generators}/model/USAGE +0 -0
- data/{generators → sc_generators}/model/model_generator.rb +0 -0
- data/{generators → sc_generators}/model/templates/fixture.js +0 -0
- data/{generators → sc_generators}/model/templates/model.js +0 -0
- data/{generators → sc_generators}/model/templates/test.rhtml +0 -0
- data/{generators → sc_generators}/test/USAGE +0 -0
- data/{generators → sc_generators}/test/templates/test.rhtml +0 -0
- data/{generators → sc_generators}/test/test_generator.rb +0 -0
- data/{generators → sc_generators}/view/USAGE +0 -0
- data/{generators → sc_generators}/view/templates/test.rhtml +0 -0
- data/{generators → sc_generators}/view/templates/view.js +0 -0
- data/{generators → sc_generators}/view/view_generator.rb +0 -0
- metadata +34 -34
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
|
2
|
+
* The build tools can now generate bundles with relative paths. Fixes #19
|
3
|
+
|
4
|
+
* Fixed minor typos in the generated template files closed #17
|
5
|
+
|
6
|
+
* Renamed generators to sc_generators. This avoids a conflict with Rails 2.1.
|
7
|
+
|
8
|
+
* [FIX] Applied bug fixes suggested by typo_pl to make the build tool run on windows.
|
9
|
+
|
1
10
|
* [FIX] Changed default language mapping for Japanese from jp to ja.
|
2
11
|
|
3
12
|
== SproutCore 0.9.8
|
data/Manifest.txt
CHANGED
@@ -219,38 +219,6 @@ frameworks/sproutcore/views/split_divider.js
|
|
219
219
|
frameworks/sproutcore/views/tab.js
|
220
220
|
frameworks/sproutcore/views/toolbar.js
|
221
221
|
frameworks/sproutcore/views/view.js
|
222
|
-
generators/client/client_generator.rb
|
223
|
-
generators/client/README
|
224
|
-
generators/client/templates/core.js
|
225
|
-
generators/client/templates/english.lproj/body.css
|
226
|
-
generators/client/templates/english.lproj/body.rhtml
|
227
|
-
generators/client/templates/english.lproj/strings.js
|
228
|
-
generators/client/templates/main.js
|
229
|
-
generators/client/USAGE
|
230
|
-
generators/controller/controller_generator.rb
|
231
|
-
generators/controller/templates/controller.js
|
232
|
-
generators/controller/templates/test.rhtml
|
233
|
-
generators/controller/USAGE
|
234
|
-
generators/framework/framework_generator.rb
|
235
|
-
generators/framework/README
|
236
|
-
generators/framework/templates/core.js
|
237
|
-
generators/framework/templates/english.lproj/strings.js
|
238
|
-
generators/framework/USAGE
|
239
|
-
generators/language/language_generator.rb
|
240
|
-
generators/language/templates/strings.js
|
241
|
-
generators/language/USAGE
|
242
|
-
generators/model/model_generator.rb
|
243
|
-
generators/model/templates/fixture.js
|
244
|
-
generators/model/templates/model.js
|
245
|
-
generators/model/templates/test.rhtml
|
246
|
-
generators/model/USAGE
|
247
|
-
generators/test/templates/test.rhtml
|
248
|
-
generators/test/test_generator.rb
|
249
|
-
generators/test/USAGE
|
250
|
-
generators/view/templates/test.rhtml
|
251
|
-
generators/view/templates/view.js
|
252
|
-
generators/view/USAGE
|
253
|
-
generators/view/view_generator.rb
|
254
222
|
History.txt
|
255
223
|
jsdoc/app/DocFile.js
|
256
224
|
jsdoc/app/Doclet.js
|
@@ -303,6 +271,38 @@ Manifest.txt
|
|
303
271
|
Rakefile
|
304
272
|
README.txt
|
305
273
|
sc-config.rb
|
274
|
+
sc_generators/client/client_generator.rb
|
275
|
+
sc_generators/client/README
|
276
|
+
sc_generators/client/templates/core.js
|
277
|
+
sc_generators/client/templates/english.lproj/body.css
|
278
|
+
sc_generators/client/templates/english.lproj/body.rhtml
|
279
|
+
sc_generators/client/templates/english.lproj/strings.js
|
280
|
+
sc_generators/client/templates/main.js
|
281
|
+
sc_generators/client/USAGE
|
282
|
+
sc_generators/controller/controller_generator.rb
|
283
|
+
sc_generators/controller/templates/controller.js
|
284
|
+
sc_generators/controller/templates/test.rhtml
|
285
|
+
sc_generators/controller/USAGE
|
286
|
+
sc_generators/framework/framework_generator.rb
|
287
|
+
sc_generators/framework/README
|
288
|
+
sc_generators/framework/templates/core.js
|
289
|
+
sc_generators/framework/templates/english.lproj/strings.js
|
290
|
+
sc_generators/framework/USAGE
|
291
|
+
sc_generators/language/language_generator.rb
|
292
|
+
sc_generators/language/templates/strings.js
|
293
|
+
sc_generators/language/USAGE
|
294
|
+
sc_generators/model/model_generator.rb
|
295
|
+
sc_generators/model/templates/fixture.js
|
296
|
+
sc_generators/model/templates/model.js
|
297
|
+
sc_generators/model/templates/test.rhtml
|
298
|
+
sc_generators/model/USAGE
|
299
|
+
sc_generators/test/templates/test.rhtml
|
300
|
+
sc_generators/test/test_generator.rb
|
301
|
+
sc_generators/test/USAGE
|
302
|
+
sc_generators/view/templates/test.rhtml
|
303
|
+
sc_generators/view/templates/view.js
|
304
|
+
sc_generators/view/USAGE
|
305
|
+
sc_generators/view/view_generator.rb
|
306
306
|
script/destroy
|
307
307
|
script/generate
|
308
308
|
script/txt2html
|
@@ -6,7 +6,7 @@ already created one for you.)
|
|
6
6
|
|
7
7
|
Then, start the SproutCore Dev Server by running from this directory:
|
8
8
|
|
9
|
-
|
9
|
+
sc-server
|
10
10
|
|
11
11
|
This takes all the same arguments as mongrel. You can now visit your app
|
12
12
|
by going to:
|
@@ -53,13 +53,13 @@ you require them.
|
|
53
53
|
|
54
54
|
== Deploying your SproutCore App
|
55
55
|
|
56
|
-
Normally you will use the
|
56
|
+
Normally you will use the sc-server to host your application while you are
|
57
57
|
developing your code. Once you are ready to deploy, however, there are two
|
58
58
|
ways you can do it:
|
59
59
|
|
60
|
-
==== 1. Use
|
60
|
+
==== 1. Use sc-server in production.
|
61
61
|
|
62
|
-
The SproutCore server can be run in a production mode that will simply generate and cache web-optimized versions of all of your resources upon request. For a low-traffic or newer site, this approach is an easy way to get your code into production. You just replace your directory with your latest files and the
|
62
|
+
The SproutCore server can be run in a production mode that will simply generate and cache web-optimized versions of all of your resources upon request. For a low-traffic or newer site, this approach is an easy way to get your code into production. You just replace your directory with your latest files and the sc-server will start serving the new resources.
|
63
63
|
|
64
64
|
==== 2. Do a static build
|
65
65
|
|
@@ -68,7 +68,7 @@ In general, however, loading all of your resources through a Ruby-app is not the
|
|
68
68
|
If you want real speed, do a static build of your content and serve it through
|
69
69
|
lighttpd or apache. Do the static build, just run:
|
70
70
|
|
71
|
-
|
71
|
+
sc-build all
|
72
72
|
|
73
73
|
This will place a directory in tmp/build that contains all of your resources
|
74
74
|
pre-compiled and ready for static serving.
|
data/bin/sc-gen
CHANGED
@@ -22,6 +22,6 @@ require 'sproutcore'
|
|
22
22
|
|
23
23
|
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
24
24
|
|
25
|
-
RubiGen::Base.use_component_sources! [:
|
25
|
+
RubiGen::Base.use_component_sources! [:sc]
|
26
26
|
RubiGen::Scripts::Generate.new.run(ARGV, :destination => File.expand_path(Dir.pwd))
|
27
27
|
|
data/bin/sproutcore
CHANGED
@@ -35,4 +35,5 @@ source = RubiGen::PathSource.new(:application,
|
|
35
35
|
File.join(File.dirname(__FILE__), "../app_generators"))
|
36
36
|
RubiGen::Base.reset_sources
|
37
37
|
RubiGen::Base.append_sources source
|
38
|
+
RubiGen::Base.use_component_sources! [:sc, :app]
|
38
39
|
RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'sproutcore')
|
@@ -245,13 +245,17 @@ Object.extend(SC,{
|
|
245
245
|
|
246
246
|
/** The current Firefox major version number or 0 if not Firefox */
|
247
247
|
Firefox: function() {
|
248
|
+
var ret = 0;
|
248
249
|
if (Prototype.Browser.Gecko) {
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
250
|
+
if(navigator.userAgent.indexOf("Firefox") != -1)
|
251
|
+
{
|
252
|
+
ret = parseFloat((navigator.userAgent.match(/Firefox\/(.)/)[1]) || 0);
|
253
|
+
}
|
254
|
+
if (ret < 1) ret = 2; // default to version 2 if it is a Gecko browser.
|
255
|
+
}
|
256
|
+
return ret ;
|
257
|
+
}(),
|
258
|
+
|
255
259
|
isWindows: function() {
|
256
260
|
return !!(navigator.appVersion.match(/(Windows)/)) ;
|
257
261
|
}(),
|
@@ -365,11 +369,22 @@ Object.extend(Object,{
|
|
365
369
|
// treat it like a bool setting. Simplifies the common case where you need
|
366
370
|
// to make a class name match a bool.
|
367
371
|
Element.setClassName = function(element,className,flag) {
|
368
|
-
if
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
372
|
+
if(SC.isIE())
|
373
|
+
{
|
374
|
+
if (flag) {
|
375
|
+
Element.addClassName(element,className);
|
376
|
+
} else {
|
377
|
+
Element.removeClassName(element,className) ;
|
378
|
+
}
|
379
|
+
}
|
380
|
+
else
|
381
|
+
{
|
382
|
+
if (flag) {
|
383
|
+
element.addClassName(className);
|
384
|
+
} else {
|
385
|
+
element.removeClassName(className) ;
|
386
|
+
}
|
387
|
+
}
|
373
388
|
} ;
|
374
389
|
|
375
390
|
// ........................................
|
@@ -1,5 +1,11 @@
|
|
1
1
|
== GIT HEAD
|
2
2
|
|
3
|
+
|
4
|
+
* SC.Platform.Firefox now returns 2 for any gecko browser that is not Firefox.
|
5
|
+
|
6
|
+
* set() and a variety of other methods now returns this instead of the set
|
7
|
+
value. This makes it possible to do method chaining.
|
8
|
+
|
3
9
|
== 0.9.8
|
4
10
|
|
5
11
|
* [FIX] collection views now update group views appropriately.
|
@@ -146,7 +146,7 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
146
146
|
// create clone of content array if needed
|
147
147
|
var contentClone = this.get('contentClone') ;
|
148
148
|
if (!contentClone) {
|
149
|
-
|
149
|
+
this.set('contentClone', contentClone = content.clone()) ;
|
150
150
|
}
|
151
151
|
|
152
152
|
// now, record the removed objects. This may be used later.
|
@@ -501,8 +501,8 @@ SC.Drag = SC.Object.extend(
|
|
501
501
|
return null ;
|
502
502
|
},
|
503
503
|
|
504
|
-
// Search the parent nodes of the target to find another view matching the
|
505
|
-
// target. Returns null if no matching target is found.
|
504
|
+
// Search the parent nodes of the target to find another view matching the
|
505
|
+
// drop target. Returns null if no matching target is found.
|
506
506
|
_findNextDropTarget: function(target) {
|
507
507
|
while ((target = target.parentNode) && (target != SC.window)) {
|
508
508
|
if (SC.Drag._dropTargets[target._guid]) return target ;
|
@@ -34,7 +34,7 @@
|
|
34
34
|
.sc-theme .pane .shadow {
|
35
35
|
position: relative ;
|
36
36
|
border: none ;
|
37
|
-
background: #e8e8e8
|
37
|
+
background: #e8e8e8 static_url('panels/background-thin.png') repeat-x left -1px;
|
38
38
|
border-top: 1px #ddd solid;
|
39
39
|
}
|
40
40
|
|
@@ -389,7 +389,7 @@ input.show-hint {
|
|
389
389
|
vertical-align: middle ;
|
390
390
|
position: relative ;
|
391
391
|
padding-left: 48px;
|
392
|
-
background:
|
392
|
+
background: static_url('images/sc-theme-sprite.png') no-repeat ;
|
393
393
|
}
|
394
394
|
|
395
395
|
.sc-theme.blur .sc-slider-view,
|
@@ -404,7 +404,7 @@ input.show-hint {
|
|
404
404
|
.sc-theme .sc-slider-view .outer {
|
405
405
|
display: block;
|
406
406
|
height: 18px;
|
407
|
-
background:
|
407
|
+
background: static_url('images/sc-theme-sprite.png') no-repeat ;
|
408
408
|
padding-right: 48px;
|
409
409
|
position: relative ;
|
410
410
|
}
|
@@ -421,7 +421,7 @@ input.show-hint {
|
|
421
421
|
.sc-theme .sc-slider-view .inner {
|
422
422
|
display: block;
|
423
423
|
height: 18px;
|
424
|
-
background:
|
424
|
+
background: static_url('images/sc-theme-sprite.png') repeat-x ;
|
425
425
|
width: 98px;
|
426
426
|
position: relative ;
|
427
427
|
}
|
@@ -443,7 +443,7 @@ input.show-hint {
|
|
443
443
|
margin-left: -9px;
|
444
444
|
left: 50%;
|
445
445
|
top: 0;
|
446
|
-
background:
|
446
|
+
background: static_url('images/sc-theme-sprite.png') no-repeat
|
447
447
|
}
|
448
448
|
|
449
449
|
.sc-theme.focus .sc-slider-view .sc-handle {
|
@@ -162,7 +162,8 @@ SC.Binding = SC.Object.extend({
|
|
162
162
|
this._lastFromValue = value ;
|
163
163
|
|
164
164
|
// send along to the 'from' source.
|
165
|
-
|
165
|
+
tuple[0].set(tuple[1],value) ;
|
166
|
+
var result = tuple[0].get(tuple[1]);
|
166
167
|
if (result) this._lastFromPropertyRevision = result.propertyRevision ;
|
167
168
|
|
168
169
|
// now that it has been set, the FROM object might not allow some
|
@@ -50,7 +50,8 @@ SC.InputManager = SC.Object.extend(
|
|
50
50
|
return responder[methodName]( event );
|
51
51
|
}
|
52
52
|
}
|
53
|
-
if
|
53
|
+
// if(cmd == "space") chr = " ";
|
54
|
+
if ( chr && responder.respondsTo('insertText'))
|
54
55
|
{
|
55
56
|
// if we haven't returned yet and there is plain text, then do an insert of the text.
|
56
57
|
return responder.insertText(chr);
|
@@ -132,7 +133,7 @@ SC.MODIFIER_KEYS = {
|
|
132
133
|
|
133
134
|
SC.FUNCTION_KEYS = {
|
134
135
|
8: 'backspace', 9: 'tab', 13: 'return', 19: 'pause', 27: 'escape',
|
135
|
-
|
136
|
+
33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home',
|
136
137
|
37: 'left', 38: 'up', 39: 'right', 40: 'down', 44: 'printscreen',
|
137
138
|
45: 'insert', 46: 'delete', 112: 'f1', 113: 'f2', 114: 'f3', 115: 'f4',
|
138
139
|
116: 'f5', 117: 'f7', 119: 'f8', 120: 'f9', 121: 'f10', 122: 'f11',
|
@@ -140,12 +141,12 @@ SC.FUNCTION_KEYS = {
|
|
140
141
|
} ;
|
141
142
|
|
142
143
|
SC.PRINTABLE_KEYS = {
|
143
|
-
48:"0", 49:"1", 50:"2", 51:"3", 52:"4", 53:"5", 54:"6", 55:"7",
|
144
|
-
57:"9", 59:";", 61:"=", 65:"a", 66:"b", 67:"c", 68:"d", 69:"e",
|
145
|
-
71:"g", 72:"h", 73:"i", 74:"j", 75:"k", 76:"l", 77:"m", 78:"n",
|
146
|
-
80:"p", 81:"q", 82:"r", 83:"s", 84:"t", 85:"u", 86:"v", 87:"w",
|
147
|
-
89:"y", 90:"z", 107:"+", 109:"-", 110:".", 188:",", 190:".",
|
148
|
-
192:"`", 219:"[", 220:"\\", 221:"]", 222:"\""
|
144
|
+
32: ' ', 48:"0", 49:"1", 50:"2", 51:"3", 52:"4", 53:"5", 54:"6", 55:"7",
|
145
|
+
56:"8", 57:"9", 59:";", 61:"=", 65:"a", 66:"b", 67:"c", 68:"d", 69:"e",
|
146
|
+
70:"f", 71:"g", 72:"h", 73:"i", 74:"j", 75:"k", 76:"l", 77:"m", 78:"n",
|
147
|
+
79:"o", 80:"p", 81:"q", 82:"r", 83:"s", 84:"t", 85:"u", 86:"v", 87:"w",
|
148
|
+
88:"x", 89:"y", 90:"z", 107:"+", 109:"-", 110:".", 188:",", 190:".",
|
149
|
+
191:"/", 192:"`", 219:"[", 220:"\\", 221:"]", 222:"\""
|
149
150
|
} ;
|
150
151
|
|
151
152
|
// make reverse keycode lookup for using in unit tests...
|
@@ -313,7 +313,7 @@ SC._PathModule = {
|
|
313
313
|
|
314
314
|
// find first node with an attribute matching then named value.
|
315
315
|
$P: function(el, attr, value, levels) {
|
316
|
-
var ret = SC._PathModule.$$
|
316
|
+
var ret = SC._PathModule.$$P(el, attr, value,levels,1,false) ;
|
317
317
|
return (ret.length>0) ? ret[0] : null ;
|
318
318
|
},
|
319
319
|
|
@@ -114,7 +114,7 @@ view_helper :view do
|
|
114
114
|
end
|
115
115
|
|
116
116
|
# render the basic content
|
117
|
-
content { (@tag == 'img') ?
|
117
|
+
content { (@tag == 'img') ? %(<#{@tag} #{attributes} />) : %(#{ot}#{@inner_html}#{ct}) }
|
118
118
|
|
119
119
|
end
|
120
120
|
|
@@ -194,6 +194,8 @@ view_helper :image_view do
|
|
194
194
|
property :content
|
195
195
|
property :value
|
196
196
|
|
197
|
+
attribute :src, static_url('blank')
|
198
|
+
|
197
199
|
var :tag, 'img'
|
198
200
|
css_class_names << 'sc-image-view'
|
199
201
|
end
|
@@ -8,8 +8,8 @@
|
|
8
8
|
# See the comments in this file for more information on what you can
|
9
9
|
# change.
|
10
10
|
-%>
|
11
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
|
12
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-
|
11
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
12
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
13
13
|
<html>
|
14
14
|
<head>
|
15
15
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
@@ -39,6 +39,10 @@ end
|
|
39
39
|
# The icon for the menu item. No icon will show if this is not set.
|
40
40
|
#
|
41
41
|
# :shortcut =>
|
42
|
+
# You must pass the actualy bit of HTML you want to display as a keyboard
|
43
|
+
# shortcut
|
44
|
+
#
|
45
|
+
# THE FOLLOWING PREVIOUS BEHAVIOR IS CURRENTLY DISABLED
|
42
46
|
# The shortcut key for this menu item. Shortcuts are only active when
|
43
47
|
# the anchorview the popup menu is attached to is part of the in-focus
|
44
48
|
# pane. Shortcuts should be named in the standard input manager
|
@@ -68,7 +72,8 @@ view_helper :menu_item_view, :extends => :button_view do
|
|
68
72
|
|
69
73
|
# HTML
|
70
74
|
var :tag, 'li'
|
71
|
-
var
|
75
|
+
var :shortcut
|
76
|
+
# var(:shortcut) { |sc| sc.split('_').map { |x| x.capitalize } * '-' }
|
72
77
|
css_class_names << 'menu-item'
|
73
78
|
|
74
79
|
@my_href = @href || 'javascript:;'
|
@@ -159,7 +159,38 @@ SC.Observable = {
|
|
159
159
|
// used as properties.
|
160
160
|
|
161
161
|
/**
|
162
|
-
|
162
|
+
Retrieves the value of key from the object.
|
163
|
+
|
164
|
+
This method is generally very similar to using object[key] or object.key,
|
165
|
+
however it supports both computed properties and the unknownProperty
|
166
|
+
handler.
|
167
|
+
|
168
|
+
*Computed Properties*
|
169
|
+
|
170
|
+
Computed properties are methods defined with the property() modifier
|
171
|
+
declared at the end, such as:
|
172
|
+
|
173
|
+
{{{
|
174
|
+
fullName: function() {
|
175
|
+
return this.getEach('firstName', 'lastName').compact().join(' ');
|
176
|
+
}.property('firstName', 'lastName')
|
177
|
+
}}}
|
178
|
+
|
179
|
+
When you call get() on a computed property, the property function will be
|
180
|
+
called and the return value will be returned instead of the function
|
181
|
+
itself.
|
182
|
+
|
183
|
+
*Unknown Properties*
|
184
|
+
|
185
|
+
Likewise, if you try to call get() on a property whose values is
|
186
|
+
undefined, the unknownProperty() method will be called on the object.
|
187
|
+
If this method reutrns any value other than undefined, it will be returned
|
188
|
+
instead. This allows you to implement "virtual" properties that are
|
189
|
+
not defined upfront.
|
190
|
+
|
191
|
+
@param key {String} the property to retrieve
|
192
|
+
@returns {Object} the property value or undefined.
|
193
|
+
|
163
194
|
*/
|
164
195
|
get: function(key) {
|
165
196
|
var ret = this[key] ;
|
@@ -171,7 +202,51 @@ SC.Observable = {
|
|
171
202
|
},
|
172
203
|
|
173
204
|
/**
|
174
|
-
|
205
|
+
Sets the key equal to value.
|
206
|
+
|
207
|
+
This method is generally very similar to calling object[key] = value or
|
208
|
+
object.key = value, except that it provides support for computed
|
209
|
+
properties, the unknownProperty() method and property observers.
|
210
|
+
|
211
|
+
*Computed Properties*
|
212
|
+
|
213
|
+
If you try to set a value on a key that has a computed property handler
|
214
|
+
defined (see the get() method for an example), then set() will call
|
215
|
+
that method, passing both the value and key instead of simply changing
|
216
|
+
the value itself. This is useful for those times when you need to
|
217
|
+
implement a property that is composed of one or more member
|
218
|
+
properties.
|
219
|
+
|
220
|
+
*Unknown Properties*
|
221
|
+
|
222
|
+
If you try to set a value on a key that is undefined in the target
|
223
|
+
object, then the unknownProperty() handler will be called instead. This
|
224
|
+
gives you an opportunity to implement complex "virtual" properties that
|
225
|
+
are not predefined on the obejct. If unknownProperty() returns
|
226
|
+
undefined, then set() will simply set the value on the object.
|
227
|
+
|
228
|
+
*Property Observers*
|
229
|
+
|
230
|
+
In addition to changing the property, set() will also register a
|
231
|
+
property change with the object. Unless you have placed this call
|
232
|
+
inside of a beginPropertyChanges() and endPropertyChanges(), any "local"
|
233
|
+
observers (i.e. observer methods declared on the same object), will be
|
234
|
+
called immediately. Any "remote" observers (i.e. observer methods
|
235
|
+
declared on another object) will be placed in a queue and called at a
|
236
|
+
later time in a coelesced manner.
|
237
|
+
|
238
|
+
*Chaining*
|
239
|
+
|
240
|
+
In addition to property changes, set() returns the value of the object
|
241
|
+
itself so you can do chaining like this:
|
242
|
+
|
243
|
+
{{{
|
244
|
+
record.set('firstName', 'Charles').set('lastName', 'Jolley');
|
245
|
+
}}}
|
246
|
+
|
247
|
+
@param key {String} the property to set
|
248
|
+
@param value {Object} the value to set or null.
|
249
|
+
@returns {this}
|
175
250
|
*/
|
176
251
|
set: function(key, value) {
|
177
252
|
var func = this[key] ;
|
@@ -188,31 +263,45 @@ SC.Observable = {
|
|
188
263
|
|
189
264
|
// post out notifications.
|
190
265
|
this.propertyDidChange(key, ret) ;
|
191
|
-
return
|
266
|
+
return this ;
|
192
267
|
},
|
193
268
|
|
194
269
|
/**
|
195
|
-
|
270
|
+
Sets the property only if the passed value is different from the
|
196
271
|
current value. Depending on how expensive a get() is on this property,
|
197
272
|
this may be more efficient.
|
273
|
+
|
274
|
+
@param key {String} the key to change
|
275
|
+
@param value {Object} the value to change
|
276
|
+
@returns {this}
|
198
277
|
*/
|
199
278
|
setIfChanged: function(key, value) {
|
200
|
-
return (this.get(key) !== value) ? this.set(key, value) :
|
279
|
+
return (this.get(key) !== value) ? this.set(key, value) : this ;
|
201
280
|
},
|
202
281
|
|
203
282
|
/**
|
204
|
-
|
283
|
+
Navigates the property path, returning the value at that point.
|
284
|
+
|
285
|
+
If any object in the path is undefined, returns undefined.
|
205
286
|
*/
|
206
287
|
getPath: function(path) {
|
207
288
|
var tuple = SC.Object.tupleForPropertyPath(path, this) ;
|
208
|
-
if (tuple[0]
|
289
|
+
if (tuple[0] === null) return undefined ;
|
209
290
|
return tuple[0].get(tuple[1]) ;
|
210
291
|
},
|
211
292
|
|
293
|
+
/**
|
294
|
+
Navigates the property path, finally setting the value.
|
295
|
+
|
296
|
+
@param path {String} the property path to set
|
297
|
+
@param value {Object} the value to set
|
298
|
+
@returns {this}
|
299
|
+
*/
|
212
300
|
setPath: function(path, value) {
|
213
301
|
var tuple = SC.Object.tupleForPropertyPath(path, this) ;
|
214
302
|
if (tuple[0] == null) return null ;
|
215
|
-
|
303
|
+
tuple[0].set(tuple[1], value) ;
|
304
|
+
return this;
|
216
305
|
},
|
217
306
|
|
218
307
|
|
@@ -241,7 +330,8 @@ SC.Observable = {
|
|
241
330
|
@returns {Number} new value of property
|
242
331
|
*/
|
243
332
|
incrementProperty: function(key) {
|
244
|
-
|
333
|
+
this.set(key,(this.get(key) || 0)+1);
|
334
|
+
return this.get(key) ;
|
245
335
|
},
|
246
336
|
|
247
337
|
/**
|
@@ -251,7 +341,8 @@ SC.Observable = {
|
|
251
341
|
@returns {Number} new value of property
|
252
342
|
*/
|
253
343
|
decrementProperty: function(key) {
|
254
|
-
|
344
|
+
this.set(key,(this.get(key) || 0) - 1 ) ;
|
345
|
+
return this.get(key) ;
|
255
346
|
},
|
256
347
|
|
257
348
|
/**
|
@@ -266,7 +357,8 @@ SC.Observable = {
|
|
266
357
|
if (value === undefined) value = true ;
|
267
358
|
if (alt == undefined) alt = false ;
|
268
359
|
value = (this.get(key) == value) ? alt : value ;
|
269
|
-
|
360
|
+
this.set(key,value);
|
361
|
+
return this.get(key) ;
|
270
362
|
},
|
271
363
|
|
272
364
|
/**
|
@@ -275,6 +367,10 @@ SC.Observable = {
|
|
275
367
|
This is a generic property handler. If you define it, it will be called
|
276
368
|
when the named property is not yet set in the object. The default does
|
277
369
|
nothing.
|
370
|
+
|
371
|
+
@param key {String} the key that was requested
|
372
|
+
@param value {Object} The value if called as a setter, undefined if called as a getter.
|
373
|
+
@returns {Object} The new value for key.
|
278
374
|
*/
|
279
375
|
unknownProperty: function(key,value) {
|
280
376
|
if (!(value === undefined)) { this[key] = value; }
|
@@ -313,10 +409,11 @@ SC.Observable = {
|
|
313
409
|
When you are done making changes, all endPropertyChanges() to allow
|
314
410
|
notification to resume.
|
315
411
|
|
316
|
-
@returns {
|
412
|
+
@returns {this}
|
317
413
|
*/
|
318
414
|
beginPropertyChanges: function() {
|
319
415
|
this._kvo().changes++ ;
|
416
|
+
return this;
|
320
417
|
},
|
321
418
|
|
322
419
|
/**
|
@@ -329,11 +426,12 @@ SC.Observable = {
|
|
329
426
|
notifications. When you are done making changes, call this method to allow
|
330
427
|
notification to resume.
|
331
428
|
|
332
|
-
@returns {
|
429
|
+
@returns {this}
|
333
430
|
*/
|
334
431
|
endPropertyChanges: function() {
|
335
432
|
var kvo = this._kvo() ; kvo.changes--;
|
336
433
|
if (kvo.changes <= 0) this._notifyPropertyObservers() ;
|
434
|
+
return this ;
|
337
435
|
},
|
338
436
|
|
339
437
|
/**
|
@@ -350,10 +448,11 @@ SC.Observable = {
|
|
350
448
|
and cause notifications to be delivered more often than you would like.
|
351
449
|
|
352
450
|
@param key {String} The property key that is about to change.
|
353
|
-
@returns {
|
451
|
+
@returns {this}
|
354
452
|
*/
|
355
453
|
propertyWillChange: function(key) {
|
356
454
|
this._kvo().changes++ ;
|
455
|
+
return this ;
|
357
456
|
},
|
358
457
|
|
359
458
|
/**
|
@@ -371,12 +470,13 @@ SC.Observable = {
|
|
371
470
|
|
372
471
|
@param key {String} The property key that has just changed.
|
373
472
|
@param value {Object} The new value of the key. May be null.
|
374
|
-
@returns {
|
473
|
+
@returns {this}
|
375
474
|
*/
|
376
475
|
propertyDidChange: function(key,value) {
|
377
476
|
this._kvo().changed[key] = value ;
|
378
477
|
var kvo = this._kvo() ; kvo.changes--; kvo.revision++ ;
|
379
478
|
if (kvo.changes <= 0) this._notifyPropertyObservers() ;
|
479
|
+
return this ;
|
380
480
|
},
|
381
481
|
|
382
482
|
/**
|
@@ -389,11 +489,12 @@ SC.Observable = {
|
|
389
489
|
|
390
490
|
@param key {String} The property key that has just changed.
|
391
491
|
@param value {Object} The new value of the key. May be null.
|
392
|
-
@returns {
|
492
|
+
@returns {this}
|
393
493
|
*/
|
394
494
|
notifyPropertyChange: function(key, value) {
|
395
495
|
this.propertyWillChange(key) ;
|
396
496
|
this.propertyDidChange(key, value) ;
|
497
|
+
return this;
|
397
498
|
},
|
398
499
|
|
399
500
|
/**
|
@@ -406,10 +507,11 @@ SC.Observable = {
|
|
406
507
|
In those cases, you can simply call this method to notify all property
|
407
508
|
observers immediately. Note that this ignores property groups.
|
408
509
|
|
409
|
-
@returns {
|
510
|
+
@returns {this}
|
410
511
|
*/
|
411
512
|
allPropertiesDidChange: function() {
|
412
513
|
this._notifyPropertyObservers(true) ;
|
514
|
+
return this ;
|
413
515
|
},
|
414
516
|
|
415
517
|
/**
|