sproutcore 1.6.0.1 → 1.7.1.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/CHANGELOG +21 -0
  2. data/Gemfile +5 -0
  3. data/Rakefile +26 -13
  4. data/VERSION.yml +2 -2
  5. data/lib/Buildfile +43 -4
  6. data/lib/buildtasks/build.rake +10 -0
  7. data/lib/buildtasks/helpers/file_rule.rb +22 -0
  8. data/lib/buildtasks/helpers/file_rule_list.rb +137 -0
  9. data/lib/buildtasks/manifest.rake +133 -122
  10. data/lib/frameworks/sproutcore/CHANGELOG.md +69 -2
  11. data/lib/frameworks/sproutcore/apps/tests/english.lproj/strings.js +1 -0
  12. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +28 -22
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -5
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/controller.js +1 -1
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/controls/button.js +18 -13
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/bind.js +5 -3
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/collection.js +2 -0
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +80 -0
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +84 -116
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +8 -5
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +157 -157
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +5 -3
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +6 -6
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +10 -7
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +106 -0
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/collection.js +18 -0
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +71 -1
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/attribute_bindings_test.js +38 -0
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/class_name_bindings_test.js +47 -0
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +18 -18
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +42 -10
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +26 -1
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +14 -8
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +158 -1
  35. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +15 -2
  36. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +108 -108
  37. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +1 -1
  38. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -4
  39. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/error_methods.js +2 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +26 -0
  41. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +7 -0
  42. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/error_methods.js +1 -1
  43. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +4 -1
  44. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +6 -0
  45. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +26 -5
  46. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +97 -96
  47. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -3
  48. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +17 -4
  49. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +7 -7
  50. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +7 -5
  51. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +12 -3
  52. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +23 -14
  53. data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +5 -1
  54. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +28 -0
  55. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +235 -0
  56. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +363 -0
  57. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +250 -0
  58. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +92 -0
  59. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +25 -0
  60. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +33 -0
  61. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +76 -0
  62. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +50 -0
  63. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +143 -0
  64. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +258 -0
  65. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +1164 -0
  66. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +332 -0
  67. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +236 -0
  68. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +347 -0
  69. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +15 -0
  70. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +10 -0
  71. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +804 -0
  72. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +133 -0
  73. data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +3 -3
  74. data/lib/frameworks/sproutcore/frameworks/foundation/validators/number.js +3 -1
  75. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +3 -3
  76. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +2 -1
  77. data/lib/frameworks/sproutcore/frameworks/media/views/controls.js +2 -1
  78. data/lib/frameworks/sproutcore/frameworks/media/views/media_slider.js +2 -4
  79. data/lib/frameworks/sproutcore/frameworks/media/views/mini_controls.js +2 -4
  80. data/lib/frameworks/sproutcore/frameworks/media/views/simple_controls.js +2 -4
  81. data/lib/frameworks/sproutcore/frameworks/media/views/video.js +2 -2
  82. data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +29 -3
  83. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
  84. data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +1 -1
  85. data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +2 -1
  86. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
  87. data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +2 -2
  88. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +1 -1
  89. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
  90. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +1 -1
  91. data/lib/gen/app/templates/apps/@target_name@/Buildfile +3 -5
  92. data/lib/gen/app/templates/apps/@target_name@/resources/_theme.css +18 -0
  93. data/lib/gen/project/templates/@filename@/Buildfile +2 -2
  94. data/lib/sproutcore/builders/chance_file.rb +9 -16
  95. data/lib/sproutcore/builders/html.rb +2 -1
  96. data/lib/sproutcore/builders/minify.rb +4 -35
  97. data/lib/sproutcore/builders/module.rb +38 -1
  98. data/lib/sproutcore/builders/split.rb +63 -0
  99. data/lib/sproutcore/builders/strings.rb +7 -1
  100. data/lib/sproutcore/builders.rb +1 -0
  101. data/lib/sproutcore/helpers/css_split.rb +190 -0
  102. data/lib/sproutcore/helpers/entry_sorter.rb +2 -0
  103. data/lib/sproutcore/helpers/minifier.rb +40 -16
  104. data/lib/sproutcore/helpers/static_helper.rb +35 -17
  105. data/lib/sproutcore/helpers.rb +1 -1
  106. data/lib/sproutcore/models/manifest.rb +26 -0
  107. data/lib/sproutcore/models/target.rb +12 -1
  108. data/lib/sproutcore/rack/proxy.rb +244 -225
  109. data/lib/sproutcore/rack/restrict_ip.rb +67 -0
  110. data/lib/sproutcore/rack/service.rb +8 -2
  111. data/lib/sproutcore/rack.rb +1 -0
  112. data/lib/sproutcore/tools/build.rb +91 -43
  113. data/lib/sproutcore/tools/gen.rb +2 -3
  114. data/lib/sproutcore/tools/manifest.rb +22 -16
  115. data/lib/sproutcore/tools/server.rb +21 -0
  116. data/lib/sproutcore/tools.rb +102 -46
  117. data/lib/sproutcore.rb +30 -5
  118. data/spec/buildtasks/helpers/accept_list +22 -0
  119. data/spec/buildtasks/helpers/accept_list.rb +128 -0
  120. data/spec/buildtasks/helpers/list.json +11 -0
  121. data/spec/buildtasks/manifest/prepare_build_tasks/chance_2x_spec.rb +1 -39
  122. data/spec/buildtasks/manifest/prepare_build_tasks/chance_spec.rb +0 -38
  123. data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +4 -4
  124. data/spec/buildtasks/manifest/prepare_build_tasks/module_spec.rb +2 -2
  125. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_indirect_spec.rb +7 -16
  126. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_spec.rb +7 -17
  127. data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +11 -6
  128. data/spec/fixtures/builder_tests/Buildfile +2 -1
  129. data/spec/fixtures/builder_tests/apps/module_test/modules/required_module/core.js +0 -0
  130. data/spec/lib/builders/module_spec.rb +1 -1
  131. data/spec/spec_helper.rb +1 -0
  132. data/sproutcore.gemspec +4 -9
  133. data/vendor/chance/lib/chance/factory.rb +45 -0
  134. data/vendor/chance/lib/chance/instance/data_url.rb +0 -29
  135. data/vendor/chance/lib/chance/instance/slicing.rb +57 -4
  136. data/vendor/chance/lib/chance/instance/spriting.rb +112 -21
  137. data/vendor/chance/lib/chance/instance.rb +173 -28
  138. data/vendor/chance/lib/chance/parser.rb +80 -52
  139. data/vendor/chance/lib/chance.rb +25 -6
  140. data/vendor/sproutcore/SCCompiler.jar +0 -0
  141. data/vendor/sproutcore/lib/args4j-2.0.12.jar +0 -0
  142. data/vendor/sproutcore/lib/yuicompressor-2.4.2.jar +0 -0
  143. metadata +97 -38
@@ -22,37 +22,37 @@ SC._detectBrowser = function(userAgent, language) {
22
22
  @type Boolean
23
23
  */
24
24
  browser.windows = browser.isWindows = !!/windows/.test(userAgent);
25
-
25
+
26
26
  /**
27
27
  @name SC.browser.isMac
28
28
  @type Boolean
29
29
  */
30
30
  browser.mac = browser.isMac = !!/macintosh/.test(userAgent) || (/mac os x/.test(userAgent) && !/like mac os x/.test(userAgent));
31
-
31
+
32
32
  /**
33
33
  @name SC.browser.isiPhone
34
34
  @type Boolean
35
35
  */
36
36
  browser.iPhone = browser.isiPhone = !!/iphone/.test(userAgent);
37
-
37
+
38
38
  /**
39
39
  @name SC.browser.isiPod
40
40
  @type Boolean
41
41
  */
42
42
  browser.iPod = browser.isiPod = !!/ipod/.test(userAgent);
43
-
43
+
44
44
  /**
45
45
  @name SC.browser.isiPad
46
46
  @type Boolean
47
47
  */
48
48
  browser.iPad = browser.isiPad = !!/ipad/.test(userAgent);
49
-
49
+
50
50
  /**
51
51
  @name SC.browser.isiOS
52
52
  @type Boolean
53
53
  */
54
54
  browser.iOS = browser.isiOS = browser.iPhone || browser.iPod || browser.iPad;
55
-
55
+
56
56
  /**
57
57
  @name SC.browser.isAndroid
58
58
  @type Boolean
@@ -64,7 +64,7 @@ SC._detectBrowser = function(userAgent, language) {
64
64
  @type String
65
65
  */
66
66
  browser.opera = /opera/.test(userAgent) ? version : 0;
67
-
67
+
68
68
  /**
69
69
  @name SC.browser.isOpera
70
70
  @type Boolean
@@ -76,13 +76,13 @@ SC._detectBrowser = function(userAgent, language) {
76
76
  @type String
77
77
  */
78
78
  browser.msie = /msie/.test(userAgent) && !browser.opera ? version : 0;
79
-
79
+
80
80
  /**
81
81
  @name SC.browser.isIE
82
82
  @type Boolean
83
83
  */
84
84
  browser.isIE = !!browser.msie;
85
-
85
+
86
86
  /**
87
87
  @name SC.browser.isIE8OrLower
88
88
  @type Boolean
@@ -94,7 +94,7 @@ SC._detectBrowser = function(userAgent, language) {
94
94
  @type String
95
95
  */
96
96
  browser.mozilla = /mozilla/.test(userAgent) && !/(compatible|webkit|msie)/.test(userAgent) ? version : 0;
97
-
97
+
98
98
  /**
99
99
  @name SC.browser.isMozilla
100
100
  @type Boolean
@@ -106,7 +106,7 @@ SC._detectBrowser = function(userAgent, language) {
106
106
  @type String
107
107
  */
108
108
  browser.webkit = /webkit/.test(userAgent) ? webkitVersion : 0;
109
-
109
+
110
110
  /**
111
111
  @name SC.browser.isWebkit
112
112
  @type Boolean
@@ -118,7 +118,7 @@ SC._detectBrowser = function(userAgent, language) {
118
118
  @type String
119
119
  */
120
120
  browser.chrome = /chrome/.test(userAgent) ? version: 0;
121
-
121
+
122
122
  /**
123
123
  @name SC.browser.isChrome
124
124
  @type Boolean
@@ -129,8 +129,8 @@ SC._detectBrowser = function(userAgent, language) {
129
129
  @name SC.browser.mobileSafari
130
130
  @type String
131
131
  */
132
- browser.mobileSafari = /apple.*mobile.*safari/.test(userAgent) && browser.iOS ? webkitVersion : 0;
133
-
132
+ browser.mobileSafari = /apple.*mobile/.test(userAgent) && browser.iOS ? webkitVersion : 0;
133
+
134
134
  /**
135
135
  @name SC.browser.isMobileSafari
136
136
  @type Boolean
@@ -142,7 +142,7 @@ SC._detectBrowser = function(userAgent, language) {
142
142
  @type String
143
143
  */
144
144
  browser.iPadSafari = browser.iPad && browser.isMobileSafari ? webkitVersion : 0;
145
-
145
+
146
146
  /**
147
147
  @name SC.browser.isiPadSafari
148
148
  @type Boolean
@@ -154,7 +154,7 @@ SC._detectBrowser = function(userAgent, language) {
154
154
  @type String
155
155
  */
156
156
  browser.iPhoneSafari = browser.iPhone && browser.isMobileSafari ? webkitVersion : 0;
157
-
157
+
158
158
  /**
159
159
  @name SC.browser.isiPhoneSafari
160
160
  @type Boolean
@@ -166,19 +166,25 @@ SC._detectBrowser = function(userAgent, language) {
166
166
  @type String
167
167
  */
168
168
  browser.iPodSafari = browser.iPod && browser.isMobileSafari ? webkitVersion : 0;
169
-
169
+
170
170
  /**
171
171
  @name SC.browser.isiPodSafari
172
172
  @type Boolean
173
173
  */
174
174
  browser.isiPodSafari = !!browser.iPodSafari;
175
175
 
176
+ /**
177
+ @name SC.browser.isiOSHomeScreen
178
+ @type Boolean
179
+ */
180
+ browser.isiOSHomeScreen = browser.isMobileSafari && !/apple.*mobile.*safari/.test(userAgent);
181
+
176
182
  /**
177
183
  @name SC.browser.safari
178
184
  @type String
179
185
  */
180
186
  browser.safari = browser.webkit && !browser.chrome && !browser.iOS && !browser.android ? webkitVersion : 0;
181
-
187
+
182
188
  /**
183
189
  @name SC.browser.isSafari
184
190
  @type Boolean
@@ -190,10 +196,10 @@ SC._detectBrowser = function(userAgent, language) {
190
196
  @type String
191
197
  */
192
198
  browser.language = language.split('-', 1)[0];
193
-
199
+
194
200
  /**
195
201
  Possible values:
196
-
202
+
197
203
  - 'msie'
198
204
  - 'mozilla'
199
205
  - 'chrome'
@@ -212,14 +218,14 @@ SC._detectBrowser = function(userAgent, language) {
212
218
 
213
219
 
214
220
  /** @class
215
-
221
+
216
222
  Contains information about the browser environment that SproutCore
217
223
  is running in. String properties, such as `SC.browser.webkit` or
218
224
  `SC.browser.msie`, will have a value that represents the browser build
219
225
  number if that browser is being used. Otherwise, they will have a
220
226
  falsey value. For convenience, Boolean counterparts for all of the
221
227
  versioned properties are provided.
222
-
228
+
223
229
  @since SproutCore 1.0
224
230
  */
225
231
  SC.browser = SC._detectBrowser();
@@ -77,7 +77,7 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
77
77
  step. You can use this orderBy property, however, for displaying smaller
78
78
  arrays of content.
79
79
 
80
- Note that you can only to use addObject() to insert new objects into an
80
+ Note that you can only use addObject() to insert new objects into an
81
81
  array that is ordered. You cannot manually reorder or insert new objects
82
82
  into specific locations because the order is managed by this property
83
83
  instead.
@@ -403,15 +403,19 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
403
403
 
404
404
  _scac_arrayContentWillChange: function(start, removed, added) {
405
405
  this.arrayContentWillChange(start, removed, added);
406
- var removedObjects = this.slice(start, start+removed);
407
- this.teardownEnumerablePropertyChains(removedObjects);
406
+ if (this._kvo_enumerable_property_chains) {
407
+ var removedObjects = this.slice(start, start+removed);
408
+ this.teardownEnumerablePropertyChains(removedObjects);
409
+ }
408
410
  },
409
411
 
410
412
  _scac_arrayContentDidChange: function(start, removed, added) {
411
413
  this.arrayContentDidChange(start, removed, added);
412
- var addedObjects = this.slice(start, start+added);
414
+ if (this._kvo_enumerable_property_chains) {
415
+ var addedObjects = this.slice(start, start+added);
416
+ this.setupEnumerablePropertyChains(addedObjects);
417
+ }
413
418
  this._scac_cached = NO;
414
- this.setupEnumerablePropertyChains(addedObjects);
415
419
  this.updateSelectionAfterContentChange();
416
420
  },
417
421
 
@@ -53,7 +53,7 @@ SC.Controller = SC.Object.extend(
53
53
 
54
54
  if (!this.get('destroyContentOnReplace')) return;
55
55
 
56
- oldContent = this._oldContent,
56
+ oldContent = this._oldContent;
57
57
  newContent = this.get('content');
58
58
  if (oldContent && newContent !== oldContent && oldContent.destroy) {
59
59
  oldContent.destroy();
@@ -1,10 +1,23 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore - JavaScript Application Framework
3
+ // Copyright: ©2006-2011 Strobe Inc. and contributors.
4
+ // Portions ©2008-2011 Apple Inc. All rights reserved.
5
+ // License: Licensed under MIT license (see license.js)
6
+ // ==========================================================================
7
+
8
+ sc_require('mixins/action_support');
1
9
  sc_require('views/template');
2
10
 
3
- SC.Button = SC.TemplateView.extend({
11
+ /**
12
+ @class
13
+ @extends SC.TemplateView
14
+ @extends SC.ActionSupport
15
+ */
16
+ SC.Button = SC.TemplateView.extend(SC.ActionSupport,
17
+ /** @scope SC.Button.prototype */{
18
+
4
19
  classNames: ['sc-button'],
5
20
 
6
- // Setting isActive to true will trigger the classBinding and add
7
- // 'is-active' to our layer's class names.
8
21
  mouseDown: function() {
9
22
  this.set('isActive', true);
10
23
  this._isMouseDown = YES;
@@ -25,18 +38,9 @@ SC.Button = SC.TemplateView.extend({
25
38
  return pane.get('rootResponder');
26
39
  }.property('pane').cacheable(),
27
40
 
28
- // Setting isActive to false will remove 'is-active' from our
29
- // layer's class names.
30
41
  mouseUp: function(event) {
31
42
  if (this.get('isActive')) {
32
- var action = this.get('action'),
33
- target = this.get('target') || null,
34
- rootResponder = this.get('rootResponder');
35
-
36
- if (action && rootResponder) {
37
- rootResponder.sendAction(action, target, this, this.get('pane'), null, this);
38
- }
39
-
43
+ this.fireAction();
40
44
  this.set('isActive', false);
41
45
  }
42
46
 
@@ -50,4 +54,5 @@ SC.Button = SC.TemplateView.extend({
50
54
  touchEnd: function(touch) {
51
55
  this.mouseUp(touch);
52
56
  }
57
+
53
58
  });
@@ -166,16 +166,18 @@ Handlebars.registerHelper('bindAttr', function(options) {
166
166
  return;
167
167
  }
168
168
 
169
+ var currentValue = elem.attr(attr);
170
+
169
171
  // A false result will remove the attribute from the element. This is
170
172
  // to support attributes such as disabled, whose presence is meaningful.
171
- if (result === NO) {
173
+ if (result === NO && currentValue) {
172
174
  elem.removeAttr(attr);
173
175
 
174
176
  // Likewise, a true result will set the attribute's name as the value.
175
- } else if (result === YES) {
177
+ } else if (result === YES && currentValue !== attr) {
176
178
  elem.attr(attr, attr);
177
179
 
178
- } else {
180
+ } else if (currentValue !== result) {
179
181
  elem.attr(attr, result);
180
182
  }
181
183
  };
@@ -15,6 +15,8 @@ Handlebars.registerHelper('collection', function(path, options) {
15
15
  // @if (debug)
16
16
  if (!collectionClass) {
17
17
  throw "%@ #collection: Could not find %@".fmt(data.view, path);
18
+ } else if (!SC.kindOf(collectionClass, SC.TemplateCollectionView)) {
19
+ throw "You must use a subclass of SC.TemplateCollectionView when using the #collection Handlebars helper";
18
20
  }
19
21
  // @endif
20
22
 
@@ -0,0 +1,80 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore - JavaScript Application Framework
3
+ // Copyright: ©2006-2011 Strobe Inc. and contributors.
4
+ // Portions ©2008-2011 Apple Inc. All rights reserved.
5
+ // License: Licensed under MIT license (see license.js)
6
+ // ==========================================================================
7
+
8
+ /**
9
+ @class
10
+
11
+ Implements basic target and action support for views.
12
+
13
+ @author Erich Ocean
14
+ @author Colin Campbell (colin@sproutcore.com)
15
+ @since SproutCore 1.7
16
+ */
17
+ SC.ActionSupport =
18
+ /** @scope SC.ActionSupport.prototype */ {
19
+
20
+ /**
21
+ The target object to invoke the action on when fireAction() is called.
22
+
23
+ If you set this target, the action will be called on the target object
24
+ directly when fireAction() is called. If you leave this property set to
25
+ null, then the responder chain will be searched for a view that implements
26
+ the action.
27
+
28
+ @type Object
29
+ @default null
30
+ */
31
+ target: null,
32
+
33
+ /**
34
+ The name of the action you want triggered when fireAction() is called.
35
+
36
+ This property is used in conjunction with the target property to execute
37
+ a method when fireAction() is called.
38
+
39
+ If you do not set a target, then calling fireAction() will cause the
40
+ responder chain to search for a view that implements the action you name
41
+ here. If you set a target, then fireAction() will try to call the
42
+ method on the target itself.
43
+
44
+ @type String
45
+ @default null
46
+ */
47
+ action: null,
48
+
49
+ /**
50
+ Will be sent along with the action to provide the context of the action.
51
+ This is an easy way to include information along with the action.
52
+
53
+ @type Object
54
+ @default null
55
+ */
56
+ actionContext: null,
57
+
58
+ /**
59
+ Perform the action. If an action paramter is not provided, then
60
+ the action defaults to the `action` property.
61
+
62
+ @param {String} [action] The action to fire.
63
+
64
+ @returns {Boolean} true if successful
65
+ @returns {Boolean} false otherwise
66
+ */
67
+ fireAction: function(action) {
68
+ var target = this.get('target') || null,
69
+ rootResponder = this.getPath('pane.rootResponder');
70
+
71
+ if (action === undefined) { action = this.get('action'); }
72
+
73
+ if (action && rootResponder) {
74
+ return rootResponder.sendAction(action, target, this, this.get('pane'), this.get('actionContext'), this);
75
+ }
76
+
77
+ return false;
78
+ }
79
+
80
+ };
@@ -7,60 +7,19 @@
7
7
 
8
8
  sc_require('views/template');
9
9
 
10
- /** @class */
11
-
12
- SC.TextField = SC.TemplateView.extend(
13
- /** @scope SC.TextField.prototype */ {
14
-
15
- classNames: ['sc-text-field'],
16
-
17
- /**
18
- If set to `YES` uses textarea tag instead of input to
19
- accommodate multi-line strings.
20
-
21
- @type Boolean
22
- @default NO
23
- */
24
- isMultiline: NO,
25
-
26
- // we can't use bindAttr because of a race condition:
27
- //
28
- // when `value` is set, the bindAttr observer immediately calls
29
- // `get` in order to persist it to the DOM, but because we made
30
- // the `value` property idempotent, when it gets called by
31
- // bindAttr, it fetches the not-yet-updated value from the DOM
32
- // and returns it.
33
- //
34
- // In short, because we need to be able to catch changes to the
35
- // DOM made directly, we cannot also rely on bindAttr to update
36
- // the property: a chicken-and-egg problem.
37
- template: function(){
38
- return SC.Handlebars.compile(this.get('isMultiline') ? '<textarea></textarea>' : '<input type="text">');
39
- }.property('isMultiline').cacheable(),
10
+ /**
11
+ @class
12
+ */
13
+ SC.TextFieldSupport = /** @scope SC.TextFieldSupport */{
40
14
 
41
15
  $input: function() {
42
- tagName = this.get('isMultiline') ? 'textarea' : 'input';
43
- return this.$(tagName);
16
+ return this.$('input');
44
17
  },
45
18
 
46
- didCreateLayer: function() {
47
- var self = this;
48
-
49
- var input = this.$input();
50
- input.val(this._value);
51
-
52
- if (SC.browser.msie) {
53
- SC.Event.add(input, 'focusin', this, this.focusIn);
54
- SC.Event.add(input, 'focusout', this, this.focusOut);
55
- } else {
56
- SC.Event.add(input, 'focus', this, this.focusIn);
57
- SC.Event.add(input, 'blur', this, this.focusOut);
58
- }
59
-
60
- input.bind('change', function() {
61
- self.domValueDidChange(SC.$(this));
62
- });
63
- },
19
+ /** @private
20
+ Used internally to store value because the layer may not exist
21
+ */
22
+ _value: null,
64
23
 
65
24
  /**
66
25
  The problem this property is trying to solve is twofold:
@@ -77,79 +36,18 @@ SC.TextField = SC.TemplateView.extend(
77
36
  In order to achieve (1), we need to store a local cache of the
78
37
  value, so that SproutCore can set the proper value as soon as
79
38
  the underlying DOM element is created.
80
- */
81
- value: function(key, value) {
82
- var input = this.$input();
83
-
84
- if (value !== undefined) {
85
- // We don't want to unnecessarily set the value.
86
- // Doing that could cause the selection to be lost.
87
- if (this._value !== value || input.val() !== value) {
88
- this._value = value;
89
- input.val(value);
90
- }
91
- } else if (input.length) {
92
- this._value = value = input.val();
93
- } else {
94
- value = this._value;
95
- }
96
-
97
- return value;
98
- }.property().idempotent(),
99
-
100
- domValueDidChange: function(jquery) {
101
- this.set('value', jquery.val());
102
- },
103
-
104
- focusIn: function(event) {
105
- this.becomeFirstResponder();
106
- this.tryToPerform('focus', event);
107
- },
108
-
109
- focusOut: function(event) {
110
- this.resignFirstResponder();
111
- this.tryToPerform('blur', event);
112
- },
113
-
114
- willLoseFirstResponder: function() {
115
- this.notifyPropertyChange('value');
116
- },
117
39
 
118
- keyUp: function(evt) {
119
- this.domValueDidChange(this.$input());
120
-
121
- if (evt.keyCode === SC.Event.KEY_RETURN) {
122
- return this.tryToPerform('insertNewline', evt);
123
- } else if (evt.keyCode === SC.Event.KEY_ESC) {
124
- return this.tryToPerform('cancel', evt);
125
- }
126
-
127
- return true;
128
- }
129
-
130
- });
131
-
132
- SC.TextFieldSupport = /** @scope SC.TextFieldSupport */{
133
-
134
- /** @private
135
- Used internally to store value because the layer may not exist
136
- */
137
- _value: null,
138
-
139
- /**
140
40
  @type String
141
- @default null
41
+ @default null
142
42
  */
143
43
  value: function(key, value) {
144
- var input = this.$('input');
44
+ var input = this.$input();
145
45
 
146
46
  if (value !== undefined) {
147
47
  // We don't want to unnecessarily set the value.
148
48
  // Doing that could cause the selection to be lost.
149
- if (this._value !== value || input.val() !== value) {
150
- this._value = value;
151
- input.val(value);
152
- }
49
+ if (this._value !== value) { this._value = value; }
50
+ if (input.val() !== value) { input.val(value); }
153
51
  } else {
154
52
  if (input.length > 0) {
155
53
  value = this._value = input.val();
@@ -162,7 +60,8 @@ SC.TextFieldSupport = /** @scope SC.TextFieldSupport */{
162
60
  }.property().idempotent(),
163
61
 
164
62
  didCreateLayer: function() {
165
- var input = this.$('input');
63
+ var input = this.$input(),
64
+ self = this;
166
65
 
167
66
  input.val(this._value);
168
67
 
@@ -175,6 +74,18 @@ SC.TextFieldSupport = /** @scope SC.TextFieldSupport */{
175
74
  }
176
75
  },
177
76
 
77
+ willDestroyLayerMixin: function() {
78
+ var input = this.$input();
79
+
80
+ if (SC.browser.msie) {
81
+ SC.Event.remove(input, 'focusin', this, this.focusIn);
82
+ SC.Event.remove(input, 'focusout', this, this.focusOut);
83
+ } else {
84
+ SC.Event.remove(input, 'focus', this, this.focusIn);
85
+ SC.Event.remove(input, 'blur', this, this.focusOut);
86
+ }
87
+ },
88
+
178
89
  focusIn: function(event) {
179
90
  this.becomeFirstResponder();
180
91
  this.tryToPerform('focus', event);
@@ -185,6 +96,16 @@ SC.TextFieldSupport = /** @scope SC.TextFieldSupport */{
185
96
  this.tryToPerform('blur', event);
186
97
  },
187
98
 
99
+ touchStart: function(evt) {
100
+ evt.allowDefault();
101
+ return YES;
102
+ },
103
+
104
+ touchEnd: function(evt) {
105
+ evt.allowDefault();
106
+ return YES;
107
+ },
108
+
188
109
  /** @private
189
110
  Make sure our input value is synced with any bindings.
190
111
  In some cases, such as auto-filling, a value can get
@@ -196,7 +117,13 @@ SC.TextFieldSupport = /** @scope SC.TextFieldSupport */{
196
117
  this.notifyPropertyChange('value');
197
118
  },
198
119
 
120
+ domValueDidChange: function(jquery) {
121
+ this.set('value', jquery.val());
122
+ },
123
+
199
124
  keyUp: function(event) {
125
+ this.domValueDidChange(this.$input());
126
+
200
127
  if (event.keyCode === SC.Event.KEY_RETURN) {
201
128
  return this.tryToPerform('insertNewline', event);
202
129
  } else if (event.keyCode === SC.Event.KEY_ESC) {
@@ -205,3 +132,44 @@ SC.TextFieldSupport = /** @scope SC.TextFieldSupport */{
205
132
  }
206
133
  };
207
134
 
135
+ /**
136
+ @class
137
+ @extends SC.TemplateView
138
+ @extends SC.TextFieldSupport
139
+ */
140
+ SC.TextField = SC.TemplateView.extend(SC.TextFieldSupport,
141
+ /** @scope SC.TextField.prototype */ {
142
+
143
+ classNames: ['sc-text-field'],
144
+
145
+ /**
146
+ If set to `YES` uses textarea tag instead of input to
147
+ accommodate multi-line strings.
148
+
149
+ @type Boolean
150
+ @default NO
151
+ */
152
+ isMultiline: NO,
153
+
154
+ // we can't use bindAttr because of a race condition:
155
+ //
156
+ // when `value` is set, the bindAttr observer immediately calls
157
+ // `get` in order to persist it to the DOM, but because we made
158
+ // the `value` property idempotent, when it gets called by
159
+ // bindAttr, it fetches the not-yet-updated value from the DOM
160
+ // and returns it.
161
+ //
162
+ // In short, because we need to be able to catch changes to the
163
+ // DOM made directly, we cannot also rely on bindAttr to update
164
+ // the property: a chicken-and-egg problem.
165
+ template: function(){
166
+ return SC.Handlebars.compile(this.get('isMultiline') ? '<textarea></textarea>' : '<input type="text">');
167
+ }.property('isMultiline').cacheable(),
168
+
169
+ $input: function() {
170
+ var tagName = this.get('isMultiline') ? 'textarea' : 'input';
171
+ return this.$(tagName);
172
+ }
173
+
174
+ });
175
+
@@ -260,8 +260,8 @@ SC.Pane = SC.View.extend(SC.ResponderContext,
260
260
  // if we are currently key pane, then notify key views of change also
261
261
  if (isKeyPane) {
262
262
  if (current) { current.tryToPerform('willLoseKeyResponderTo', view); }
263
- if (view) {
264
- view.tryToPerform('willBecomeKeyResponderFrom', current);
263
+ if (view) {
264
+ view.tryToPerform('willBecomeKeyResponderFrom', current);
265
265
  }
266
266
  }
267
267
 
@@ -282,10 +282,10 @@ SC.Pane = SC.View.extend(SC.ResponderContext,
282
282
 
283
283
  // and notify again if needed.
284
284
  if (isKeyPane) {
285
- if (view) {
285
+ if (view) {
286
286
  view.tryToPerform('didBecomeKeyResponderFrom', current); }
287
- if (current) {
288
- current.tryToPerform('didLoseKeyResponderTo', view);
287
+ if (current) {
288
+ current.tryToPerform('didLoseKeyResponderTo', view);
289
289
  }
290
290
  }
291
291
 
@@ -439,6 +439,9 @@ SC.Pane = SC.View.extend(SC.ResponderContext,
439
439
  if (dom && dom.parentNode) dom.parentNode.removeChild(dom) ;
440
440
  dom = null ;
441
441
 
442
+ // layer is cached by SC.View in this._view_layer, remove it so that the DOM node can be freed
443
+ this.destroyLayer();
444
+
442
445
  // remove intercept
443
446
  this._removeIntercept();
444
447