sproutcore 0.9.7 → 0.9.8

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 CHANGED
@@ -1,4 +1,8 @@
1
- == SVN HEAD
1
+ == SproutCore 0.9.8
2
+
3
+ * [FIX] Plugged memory leak in view_helper that would cause sc-server to slow down after repeated use.
4
+
5
+ == SproutCore 0.9.7
2
6
 
3
7
  * [FIX] build tools could puke on strings files that contains quotes. This should fix it.
4
8
 
@@ -1,4 +1,8 @@
1
- == SVN HEAD
1
+ == GIT HEAD
2
+
3
+ == 0.9.8
4
+
5
+ * [FIX] collection views now update group views appropriately.
2
6
 
3
7
  * [IE] offsetParent and viewportOffset() are now IE compliant.
4
8
 
@@ -13,3 +13,4 @@ http://www.sproutcore.com
13
13
  If you would like to contact the authors, you can reach the current maintainer
14
14
  at charles@sproutit.com
15
15
 
16
+
@@ -138,7 +138,7 @@ SC.Drag = SC.Object.extend(
138
138
  for(var key in this._data) {
139
139
  if (this.data.hasOwnProperty(key)) ret.push(key) ;
140
140
  }
141
- return key ;
141
+ return ret ;
142
142
  }
143
143
 
144
144
  // if that fails, then check to see if the source object is a dataSource.
@@ -100,10 +100,11 @@ view_helper :button_view do
100
100
  var :theme, :regular
101
101
  var :size, :normal
102
102
 
103
- attribute(:href) { |x| (x.nil? && (@tag.downcase.to_s == 'a')) ? 'javascript:;' : nil }
103
+ attribute(:href) { |x| (x.nil? && (@tag.downcase.to_s == 'a')) ? 'javascript:;' : x }
104
104
 
105
105
  # Add the theme to the CSS class.
106
106
  css_class_names << 'sc-button-view'
107
+ css_class_names << 'button'
107
108
  css_class_names << @theme unless @theme.nil? || @theme == false
108
109
  css_class_names << @size unless @size.nil? || @size == false
109
110
 
@@ -17,6 +17,16 @@
17
17
  */
18
18
  SC.InlineEditorDelegate = {
19
19
 
20
+ /**
21
+ This is a classname you can apply to the inline editor field
22
+ to configure it's styling, in addition to the the editor's
23
+ default style-cloning behavior.
24
+
25
+ @property inlineEditorClassName {String} A class name to use with the inline editor.
26
+ */
27
+ inlineEditorClassName: "",
28
+
29
+
20
30
  /**
21
31
  Called just before the inline edit displays itself but after it has been
22
32
  configured for display.
@@ -130,7 +130,7 @@ SC.OverlayPaneView = SC.PaneView.extend({
130
130
  },
131
131
 
132
132
  cancel: function(sender, evt) {
133
- var button = this._findViewWithKeyIn('isDefault', SC.ButtonView, this) ;
133
+ var button = this._findViewWithKeyIn('isCancel', SC.ButtonView, this) ;
134
134
  if (button) {
135
135
  button.triggerAction(evt) ;
136
136
  return true ;
@@ -44,6 +44,7 @@ Test.context("CASE 1: Auto-layout view with no padding & no border", {
44
44
 
45
45
  });
46
46
 
47
+
47
48
  // CASE 2: Auto-layout of view with padding
48
49
  // - same as Case 1, except innerFrame = frame less padding
49
50
  CASE2_OFFSET = 2;
@@ -222,6 +222,9 @@ SC.ButtonView = SC.View.extend(SC.Control,
222
222
  */
223
223
  keyEquivalent: null,
224
224
 
225
+ /** @private {String} used to store a previously defined key equiv */
226
+ _lastKeyEquivalent: null,
227
+
225
228
  performKeyEquivalent: function( keystring, evt )
226
229
  {
227
230
  if (!this.get('isEnabled')) return false;
@@ -329,12 +332,26 @@ SC.ButtonView = SC.View.extend(SC.Control,
329
332
  _isDefaultOrCancelObserver: function() {
330
333
  var isDef = !!this.get('isDefault') ;
331
334
  var isCancel = !isDef && this.get('isCancel') ;
332
-
333
- this.setClassName('def', isDef) ;
334
-
335
- var key = this.get('keyEquivalent') ;
336
- if (isDef && key != 'return') this.set('keyEquivalent', 'return') ;
337
- if (isCancel && key != 'escape') this.set('keyEquivalent', 'escape') ;
335
+ if(this.didChangeFor('defaultCancelChanged','isDefault','isCancel')) {
336
+ this.setClassName('def', isDef) ;
337
+ var key = this.get('keyEquivalent') ;
338
+ if (isDef) {
339
+ //cache the previously defined key equivalent
340
+ this._lastKeyEquivalent = key;
341
+ this.setIfChanged('keyEquivalent', 'return');
342
+ }
343
+ else if (isCancel)
344
+ {
345
+ //cache the previously defined key equivalent
346
+ this._lastKeyEquivalent = key;
347
+ this.setIfChanged('keyEquivalent', 'escape') ;
348
+ }
349
+ else
350
+ {
351
+ this.setIfChanged("keyEquivalent",this._lastKeyEquivalent);
352
+ }
353
+ }
354
+
338
355
  }.observes('isDefault', 'isCancel'),
339
356
 
340
357
  // on mouse down, set active only if enabled.
@@ -691,7 +691,7 @@ SC.CollectionView = SC.View.extend(SC.CollectionViewDelegate,
691
691
  var didChange = false ;
692
692
 
693
693
  // If this is a fullUpdate, then rebuild the itemViewsByContent hash
694
- // from scratch. This is necessary of the content of the visible range
694
+ // from scratch. This is necessary if the content or the visible range
695
695
  // might have changed.
696
696
  if (fullUpdate) {
697
697
 
@@ -1059,9 +1059,27 @@ SC.CollectionView = SC.View.extend(SC.CollectionViewDelegate,
1059
1059
  if (!ret) throw "Could not create itemView for content: %@".fmt(content);
1060
1060
 
1061
1061
  // Determine proper parent view and insert itemView if needed.
1062
- // Also update count of itemViews.
1063
- var parentView = (groupBy && content) ? this._insertGroupViewFor(content.get(groupBy), contentIndex) : this ;
1064
- if (ret.get('parentNode') != parentView) {
1062
+ // Also update count of itemViews.
1063
+ var canGroup = !!(groupBy && content) ;
1064
+ var groupValue = (canGroup) ? content.get(groupBy) : null;
1065
+ var parentView = (canGroup) ? this._insertGroupViewFor(groupValue, contentIndex) : this ;
1066
+ var curParentView = ret.get('parentNode') ;
1067
+
1068
+ if (curParentView != parentView) {
1069
+
1070
+ // if the item is already inside of another group, then it is probably
1071
+ // just being moved, so remove it from its parent group first...
1072
+ if (groupBy && curParentView) {
1073
+
1074
+ // reduce the group view count. If this it the last item in the
1075
+ // group view, the count will be <= 0 and we will need to remove t
1076
+ // the group view itself.
1077
+ if (--this._groupViewCounts[SC.guidFor(curParentView)] <= 0) {
1078
+ this._removeGroupView(curParentView, groupValue) ;
1079
+ }
1080
+
1081
+ }
1082
+
1065
1083
  parentView.appendChild(ret) ;
1066
1084
  if (groupBy) this._groupViewCounts[SC.guidFor(parentView)]++ ;
1067
1085
  }
@@ -2494,7 +2512,10 @@ SC.CollectionView = SC.View.extend(SC.CollectionViewDelegate,
2494
2512
  while(--idx >= 0) {
2495
2513
  var itemView = this.itemViewForContent(dragContent[idx]) ;
2496
2514
  if (!itemView) continue ;
2515
+
2497
2516
  var f = itemView.get('frame') ;
2517
+ f = this.convertFrameFromView(f, itemView) ;
2518
+
2498
2519
  var dom = itemView.rootElement ;
2499
2520
  if (!dom) continue ;
2500
2521
 
@@ -2510,6 +2531,7 @@ SC.CollectionView = SC.View.extend(SC.CollectionViewDelegate,
2510
2531
  // even if the CSS styles do not match. Make sure the items are
2511
2532
  // properly positioned.
2512
2533
  dom = dom.cloneNode(true) ;
2534
+
2513
2535
  Element.setStyle(dom, { position: "absolute", left: "%@px".fmt(f.x), top: "%@px".fmt(f.y), width: "%@px".fmt(f.width), height: "%@px".fmt(f.height) }) ;
2514
2536
  view.rootElement.appendChild(dom) ;
2515
2537
  }
@@ -367,7 +367,7 @@ SC.SourceListView = SC.CollectionView.extend(
367
367
  } ;
368
368
 
369
369
  var insertionPoint = this._insertionPointView ;
370
- f = { height: 0, x: 8, y: itemView.get('frame').y, width: itemView.owner.get('frame').width };
370
+ var f = this.calculateInsertionPointFrame(itemView);
371
371
  insertionPoint.set('frame', f) ;
372
372
 
373
373
  if (insertionPoint.parentNode != itemView.parentNode) {
@@ -377,6 +377,16 @@ SC.SourceListView = SC.CollectionView.extend(
377
377
 
378
378
  },
379
379
 
380
+ /**
381
+ This is the default frame for the insertion point. Override this method
382
+ if your insertion point's styling needs to be customized, or if you need
383
+ more control of the insertion point's positioning (i.e., heirarchical
384
+ placement)
385
+ */
386
+ calculateInsertionPointFrame: function(itemView) {
387
+ return { height: 0, x: 8, y: itemView.get('frame').y, width: itemView.owner.get('frame').width };
388
+ },
389
+
380
390
  hideInsertionPoint: function() {
381
391
  var insertionPoint = this._insertionPointView ;
382
392
  if (insertionPoint) insertionPoint.removeFromParent() ;
@@ -401,7 +411,7 @@ SC.SourceListView = SC.CollectionView.extend(
401
411
  var retOp = SC.DROP_BEFORE ;
402
412
 
403
413
  // search groups until we find one that matches
404
- var top = 0;
414
+ var top = 0 ;
405
415
  var idx = 0 ;
406
416
  while((ret<0) && (range = this.groupRangeForContentIndex(idx)).length>0){
407
417
  var max = top + ((range.length+headerRowCount) * rowHeight) ;
@@ -100,9 +100,7 @@ SC.TextFieldView = SC.FieldView.extend(SC.Editable,
100
100
  this._isFocused = true ;
101
101
  if (this.get('isVisibleInWindow')) {
102
102
  this.rootElement.focus();
103
-
104
- this.invokeLater(this._selectRootElement, 1) ;
105
-
103
+ this.invokeLater(this._selectRootElement, 1) ;
106
104
  }
107
105
  }
108
106
 
@@ -110,8 +108,8 @@ SC.TextFieldView = SC.FieldView.extend(SC.Editable,
110
108
  this._updateFieldHint() ;
111
109
  },
112
110
 
113
- // In IE, you can't modify functions on DOM elements so we need to wrap the call to select()
114
- // like this.
111
+ // In IE, you can't modify functions on DOM elements so we need to wrap the
112
+ // call to select() like this.
115
113
  _selectRootElement: function() {
116
114
  this.rootElement.select() ;
117
115
  },
@@ -125,8 +123,7 @@ SC.TextFieldView = SC.FieldView.extend(SC.Editable,
125
123
  this._isFocused = false ;
126
124
  this._updateFieldHint() ;
127
125
  return this.rootElement.blur() ;
128
- }
129
- else {
126
+ } else {
130
127
  this._value = this.rootElement.value ;
131
128
  this.fieldValueDidChange() ;
132
129
  this._updateFieldHint() ;
@@ -131,6 +131,12 @@ SC.InlineTextFieldView = SC.View.extend(SC.DelegateSupport, SC.InlineEditorDeleg
131
131
  this.updateViewStyle() ;
132
132
 
133
133
  var del = this._delegate ;
134
+
135
+ this._className = this.getDelegateProperty(del,"inlineEditorClassName");
136
+ if(this._className && !this.hasClassName(this._className)) {
137
+ this.setClassName(this._className,true);
138
+ }
139
+
134
140
  this.invokeDelegateMethod(del, 'inlineEditorWillBeginEditing', this) ;
135
141
  this.resizeToFit(field.getFieldValue()) ;
136
142
 
@@ -190,8 +196,11 @@ SC.InlineTextFieldView = SC.View.extend(SC.DelegateSupport, SC.InlineEditorDeleg
190
196
  // and clean up.
191
197
  this.invokeDelegateMethod(del, 'inlineEditorDidEndEditing', this, finalValue) ;
192
198
 
199
+ // If the delegate set a class name, let's clean it up:
200
+ if(this._className) this.setClassName(this._className, false);
201
+
193
202
  // cleanup cached values
194
- this._originalValue = this._delegate = this._exampleElement = this._optframe = null ;
203
+ this._originalValue = this._delegate = this._exampleElement = this._optframe = this._className = null ;
195
204
  this.set('isEditing', NO) ;
196
205
 
197
206
  // resign first responder if not done already. This may call us in a
@@ -328,6 +337,25 @@ SC.InlineTextFieldView = SC.View.extend(SC.DelegateSupport, SC.InlineEditorDeleg
328
337
  this.owner.commitEditing() ;
329
338
  return YES ;
330
339
  }
340
+ },
341
+
342
+ // Tries to find the next key view when tabbing. If the next view is
343
+ // editable, begins editing.
344
+
345
+ insertTab: function(evt)
346
+ {
347
+ var next = this.get("owner")._delegate.nextValidKeyView();
348
+ this.owner.commitEditing() ;
349
+ if(next) next.beginEditing();
350
+ return YES ;
351
+ },
352
+
353
+ insertBacktab: function(evt)
354
+ {
355
+ var prev = this.get("owner")._delegate.previousValidKeyView();
356
+ this.owner.commitEditing() ;
357
+ if(prev) prev.beginEditing();
358
+ return YES ;
331
359
  }
332
360
 
333
361
  }).outletFor('.inner-field?'),
@@ -385,6 +413,8 @@ SC.InlineTextFieldView.mixin(
385
413
  return (this.sharedEditor) ? this.sharedEditor.discardEditing() : YES ;
386
414
  },
387
415
 
416
+
417
+
388
418
  /**
389
419
  The current shared inline editor. This property will often remain NULL
390
420
  until you actually begin editing for the first time.
@@ -470,12 +470,19 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
470
470
  //
471
471
 
472
472
  /**
473
- Read-only array of currently applied classNames.
473
+ An array of currently applied classNames.
474
474
 
475
475
  @field
476
476
  @type {Array}
477
+ @param value {Array} Array of class names to apply to the element
477
478
  */
478
- classNames: function() {
479
+ classNames: function(key, value) {
480
+ if (value !== undefined) {
481
+ value = Array.from(value) ;
482
+ if (this.rootElement) this.rootElement.className = value.join(' ') ;
483
+ this._classNames = value.slice() ;
484
+ }
485
+
479
486
  if (!this._classNames) {
480
487
  var classNames = this.rootElement.className;
481
488
  this._classNames = (classNames && classNames.length > 0) ? classNames.split(' ') : [] ;
@@ -502,11 +509,9 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
502
509
  addClassName: function(className) {
503
510
  if (this.hasClassName(className)) return ; // nothing to do
504
511
 
505
- this.propertyWillChange('classNames') ;
506
512
  var classNames = this._classNames || this.get('classNames') ;
507
513
  classNames.push(className) ;
508
- if (this.rootElement) this.rootElement.className = classNames.join(' ');
509
- this.propertyDidChange('classNames') ;
514
+ this.set('classNames', classNames) ;
510
515
  return className ;
511
516
  },
512
517
 
@@ -519,11 +524,9 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
519
524
  removeClassName: function(className) {
520
525
  if (!this.hasClassName(className)) return ; // nothing to do
521
526
 
522
- this.propertyWillChange('classNames') ;
523
527
  var classNames = this._classNames || this.get('classNames') ;
524
528
  classNames = this._classNames = classNames.without(className) ;
525
- if (this.rootElement) this.rootElement.className = classNames.join(' ');
526
- this.propertyDidChange('classNames') ;
529
+ this.set('classNames', classNames) ;
527
530
  return className ;
528
531
  },
529
532
 
@@ -543,7 +543,7 @@ module SproutCore
543
543
 
544
544
  return cached[:contents]
545
545
  end
546
-
546
+
547
547
  ######################################################
548
548
  ## LOCALIZATION
549
549
  ##
@@ -2,7 +2,7 @@ module SproutCore #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 9
5
- TINY = 7
5
+ TINY = 8
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -605,16 +605,11 @@ module SproutCore
605
605
  SproutCore::ViewHelperSupport.set_helper(helper_name, hs)
606
606
 
607
607
  ## install the helper method
608
- SproutCore::ViewHelpers.class_eval %{
608
+ eval %{
609
609
  def #{helper_name}(item_id=nil, opts={}, &block)
610
610
  SproutCore::ViewHelperSupport.render_view(:#{helper_name}, item_id, opts, bundle, self, &block)
611
611
  end }
612
612
 
613
- SproutCore::ViewHelpers.class_eval %{
614
- def self.#{helper_name}(item_id=nil, opts={}, &block)
615
- SproutCore::ViewHelperSupport.render_view(:#{helper_name}, item_id, opts, bundle, self, &block)
616
- end }
617
-
618
613
  end
619
614
 
620
615
  def render_page_views
@@ -654,7 +649,7 @@ module SproutCore
654
649
 
655
650
  # restore old bundle helper.
656
651
  unless bundle.nil?
657
- @helper_bundler = old_helper_bundle
652
+ @helper_bundle = old_helper_bundle
658
653
  end
659
654
  end
660
655
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sproutcore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Jolley
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-27 00:00:00 -07:00
12
+ date: 2008-06-01 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency