sproutcore 0.9.17 → 0.9.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/History.txt +45 -2
  2. data/Manifest.txt +10 -0
  3. data/Rakefile +1 -1
  4. data/app_generators/sproutcore/templates/sc-config +8 -2
  5. data/bin/sc-server +4 -0
  6. data/clients/sc_docs/english.lproj/body.css +0 -20
  7. data/clients/sc_docs/english.lproj/body.rhtml +1 -3
  8. data/clients/sc_docs/english.lproj/strings.js +1 -1
  9. data/clients/sc_docs/french.lproj/strings.js +14 -0
  10. data/clients/sc_test_runner/english.lproj/body.css +0 -20
  11. data/clients/sc_test_runner/english.lproj/body.rhtml +1 -3
  12. data/config/hoe.rb +1 -1
  13. data/frameworks/sproutcore/HISTORY +56 -1
  14. data/frameworks/sproutcore/debug/trace.js +81 -0
  15. data/frameworks/sproutcore/debug/unittest.js +2 -1
  16. data/frameworks/sproutcore/english.lproj/buttons.css +5 -2
  17. data/frameworks/sproutcore/english.lproj/core.css +0 -16
  18. data/frameworks/sproutcore/english.lproj/images/sc-theme-sprite.png +0 -0
  19. data/frameworks/sproutcore/english.lproj/splitview.css +83 -0
  20. data/frameworks/sproutcore/english.lproj/theme.css +21 -5
  21. data/frameworks/sproutcore/foundation/object.js +23 -0
  22. data/frameworks/sproutcore/foundation/string.js +4 -3
  23. data/frameworks/sproutcore/lib/core_views.rb +43 -8
  24. data/frameworks/sproutcore/lib/form_views.rb +2 -2
  25. data/frameworks/sproutcore/lib/index.rhtml +1 -1
  26. data/frameworks/sproutcore/mixins/enumerable.js +4 -8
  27. data/frameworks/sproutcore/mixins/selection_support.js +1 -1
  28. data/frameworks/sproutcore/models/collection.js +14 -3
  29. data/frameworks/sproutcore/models/record.js +6 -5
  30. data/frameworks/sproutcore/models/store.js +3 -3
  31. data/frameworks/sproutcore/panes/picker.js +1 -0
  32. data/frameworks/sproutcore/server/rails_server.js +4 -7
  33. data/frameworks/sproutcore/server/server.js +58 -1
  34. data/frameworks/sproutcore/tests/controllers/object.rhtml +1 -1
  35. data/frameworks/sproutcore/tests/models/collection.rhtml +160 -0
  36. data/frameworks/sproutcore/tests/models/model.rhtml +15 -3
  37. data/frameworks/sproutcore/tests/views/collection/base.rhtml +120 -47
  38. data/frameworks/sproutcore/tests/views/collection/source_list_rendering.rhtml +232 -0
  39. data/frameworks/sproutcore/tests/views/view/frame.rhtml +2 -2
  40. data/frameworks/sproutcore/tests/views/view/innerFrame.rhtml +87 -85
  41. data/frameworks/sproutcore/tests/views/view/scrollFrame.rhtml +25 -26
  42. data/frameworks/sproutcore/views/collection/collection.js +5 -1
  43. data/frameworks/sproutcore/views/field/select_field.js +1 -1
  44. data/frameworks/sproutcore/views/radio_group.js +2 -2
  45. data/frameworks/sproutcore/views/split.js +191 -174
  46. data/frameworks/sproutcore/views/split_divider.js +71 -68
  47. data/frameworks/sproutcore/views/view.js +65 -25
  48. data/lib/sproutcore.rb +4 -1
  49. data/lib/sproutcore/build_tools/html_builder.rb +50 -46
  50. data/lib/sproutcore/build_tools/resource_builder.rb +17 -5
  51. data/lib/sproutcore/bundle_installer.rb +3 -1
  52. data/lib/sproutcore/bundle_manifest.rb +4 -3
  53. data/lib/sproutcore/cssmin.rb +195 -0
  54. data/lib/sproutcore/generator_helper.rb +15 -0
  55. data/lib/sproutcore/helpers/capture_helper.rb +2 -22
  56. data/lib/sproutcore/helpers/dom_id_helper.rb +14 -0
  57. data/lib/sproutcore/helpers/static_helper.rb +6 -2
  58. data/lib/sproutcore/helpers/text_helper.rb +1 -1
  59. data/lib/sproutcore/merb.rb +2 -2
  60. data/lib/sproutcore/renderers/erubis.rb +43 -0
  61. data/lib/sproutcore/renderers/haml.rb +28 -0
  62. data/lib/sproutcore/renderers/sass.rb +42 -0
  63. data/lib/sproutcore/version.rb +1 -1
  64. data/lib/sproutcore/view_helpers.rb +40 -46
  65. data/sc_generators/controller/controller_generator.rb +1 -1
  66. data/sc_generators/language/USAGE +5 -7
  67. data/sc_generators/language/language_generator.rb +1 -1
  68. data/sc_generators/language/templates/strings.js +5 -1
  69. data/sc_generators/model/model_generator.rb +1 -1
  70. data/sc_generators/test/test_generator.rb +1 -1
  71. data/sc_generators/view/view_generator.rb +1 -1
  72. metadata +12 -5
@@ -6,104 +6,107 @@
6
6
  require('views/view') ;
7
7
  require('views/split');
8
8
 
9
- /**
9
+ /**
10
10
  @class
11
11
 
12
- A SplitDividerView displays a divider between two split views. Clicking
13
- and dragging the divider will change the thickness of the view either to
14
- the left or right of the divider, depending on which side of the flexible
15
- view the divider is on.
16
-
17
- Double-clicking will try to collapse the same view so it is not visible
18
- unless you have canCollapse disabled on the SplitView.
19
-
20
- This view must be a direct child of the split view it works with.
21
-
12
+ A SplitDividerView displays a divider between two views within a SplitView.
13
+ Clicking and dragging the divider will change the thickness of each view
14
+ either to the top/left or bottom/right of the divider.
15
+
16
+ Double-clicking on the SplitDividerView will try to collapse the first
17
+ view within the SplitView that has property canCollapse set to true,
18
+ so it is not visible, unless you have canCollapse disabled on the SplitView.
19
+
20
+ This view must be a direct child of the split view it works with. It must
21
+ be surrounded by two other views.
22
+
22
23
  @extends SC.View
23
-
24
+
24
25
  @author Charles Jolley
26
+ @author Lawrence Pit
25
27
  */
26
28
  SC.SplitDividerView = SC.View.extend(
27
29
  /** @scope SC.SplitDividerView.prototype */ {
28
-
30
+
29
31
  emptyElement: '<div class="sc-split-divider-view"></div>',
30
32
 
31
- /**
32
- Returns the view to be managed by the divider view.
33
- */
34
- targetView: function() {
35
- var splitView = this.get('parentNode') ;
36
- if (!splitView) return null ;
37
-
38
- var flexibleView = splitView.computeFlexibleView() ;
39
- var views = splitView.get('childNodes') ;
40
- var myIndex = views.indexOf(this) ;
41
- var flexibleIndex = views.indexOf(flexibleView) ;
42
-
43
- if (myIndex < 0) throw "SplitDividerView must belong to the SplitView";
44
-
45
- return (myIndex <= flexibleIndex) ? this.get('previousSibling') : this.get('nextSibling') ;
46
-
47
- }.property(),
48
-
49
33
  mouseDown: function(evt) {
50
-
51
- var splitView = this.get('parentNode') ;
52
- if (!splitView) return ;
53
-
54
34
  // cache some info for later use.
55
35
  this._mouseDownLocation = Event.pointerLocation(evt) ;
36
+ this._splitView = this.get('parentNode') ;
37
+ this._tlView = this.get('previousSibling') ;
38
+ this._brView = this.get('nextSibling') ;
39
+ this._originalTopLeftThickness = this._splitView.getThicknessForView(this._tlView) ;
40
+ this._direction = this._splitView.get('layoutDirection') ;
56
41
 
57
- this._targetView = this.get('targetView') ;
58
-
59
- // determine the view to change.
60
- this._originalThickness = splitView.thicknessForView(this._targetView);
61
-
62
- this._direction = splitView.get('layoutDirection') ;
63
-
64
42
  // return true so we can track mouse dragged.
65
43
  return true ;
66
44
  },
67
-
45
+
68
46
  mouseDragged: function(evt) {
69
-
70
- // calculate new thickness
47
+ // calculate new thickness requested by mouse
71
48
  var loc = Event.pointerLocation(evt) ;
72
-
49
+
73
50
  if (this._direction == SC.HORIZONTAL) {
74
51
  var offset = loc.x - this._mouseDownLocation.x ;
75
52
  } else {
76
53
  var offset = loc.y - this._mouseDownLocation.y ;
77
54
  }
78
55
 
79
- var thickness = this._originalThickness + offset ;
80
- var splitView = this.get('parentNode') ;
81
- splitView.setThicknessForView(this._targetView, thickness) ;
82
-
56
+ var proposedThickness = this._originalTopLeftThickness + offset ;
57
+ this._splitView.setThicknessForView(this._tlView, proposedThickness) ;
58
+ this._setCursorStyle() ;
83
59
  return true ;
84
60
  },
85
-
61
+
86
62
  // clear left overs.
87
63
  mouseUp: function(evt) {
88
- this._targetView = this._originalThickness = this._direction = this._mouseDownLocation = null ;
64
+ this._mouseDownLocation = this._originalTopLeftThickness = null ;
89
65
  },
90
-
66
+
91
67
  doubleClick: function(evt) {
92
- var splitView = this.get('parentNode') ;
93
- if (!splitView) return; // nothing to do.
94
-
95
- // try to collapse or un-collapse.
96
- var targetView = this.get('targetView');
97
- var isCollapsed = targetView.get('isCollapsed') || NO;
98
-
99
- // do not collapse if not allowed.
100
- if (!isCollapsed && !splitView.canCollapseView(targetView)) return;
101
-
102
- // now set the collapsed state and layout.
103
- targetView.set('isCollapsed', !isCollapsed) ;
104
- splitView.layout() ;
105
-
68
+ var view = this._tlView ;
69
+ var isCollapsed = view.get('isCollapsed') || NO ;
70
+ if (!isCollapsed && !this._splitView.canCollapseView(view)) {
71
+ view = this._brView ;
72
+ isCollapsed = view.get('isCollapsed') || NO ;
73
+ if (!isCollapsed && !this._splitView.canCollapseView(view)) return;
74
+ }
75
+
76
+ if (!isCollapsed) {
77
+ // remember thickness in it's uncollapsed state
78
+ view._uncollapsedThickness = this._splitView.getThicknessForView(view) ;
79
+ // and collapse
80
+ this._splitView.setThicknessForView(view, 0) ;
81
+ // if however the splitview decided not to collapse, clear:
82
+ if (!view.get("isCollapsed")) {
83
+ view._uncollapsedThickness = null;
84
+ }
85
+ } else {
86
+ // uncollapse to the last thickness in it's uncollapsed state
87
+ this._splitView.setThicknessForView(view, view._uncollapsedThickness) ;
88
+ view._uncollapsedThickness = null ;
89
+ }
90
+ this._setCursorStyle() ;
106
91
  return true ;
92
+ },
93
+
94
+ _setCursorStyle: function() {
95
+ tlThickness = this._splitView.getThicknessForView(this._tlView) ;
96
+ brThickness = this._splitView.getThicknessForView(this._brView) ;
97
+ if (this._tlView.get('isCollapsed') ||
98
+ tlThickness == this._tlView.get("minThickness") ||
99
+ brThickness == this._brView.get("maxThickness"))
100
+ {
101
+ this.setStyle({cursor: this._direction == SC.HORIZONTAL ? "e-resize" : "s-resize" }) ;
102
+ } else if (this._brView.get('isCollapsed') ||
103
+ tlThickness == this._tlView.get("maxThickness") ||
104
+ brThickness == this._brView.get("minThickness"))
105
+ {
106
+ this.setStyle({cursor: this._direction == SC.HORIZONTAL ? "w-resize" : "n-resize" }) ;
107
+ } else {
108
+ this.setStyle({cursor: this._direction == SC.HORIZONTAL ? "ew-resize" : "ns-resize" }) ;
109
+ }
107
110
  }
108
-
111
+
109
112
  });
@@ -949,7 +949,7 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
949
949
 
950
950
  var f ;
951
951
  if (this._innerFrame == null) {
952
-
952
+
953
953
  // get the base frame
954
954
  // The _collectInnerFrame function is set at the bottom of this file
955
955
  // based on the browser type.
@@ -970,19 +970,34 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
970
970
 
971
971
  // fix the x & y with the clientTop/clientLeft
972
972
  var clientLeft, clientTop ;
973
- if (el.clientLeft == null) {
974
- clientLeft = parseInt(this.getStyle('border-left-width'),0) || 0 ;
975
- } else clientLeft = el.clientLeft ;
973
+
974
+ if (SC.Platform.IE) {
975
+ if (!el.width) {
976
+ clientLeft = parseInt(this.getStyle('border-left-width'),0) || 0 ;
977
+ } else clientLeft = el.clientLeft ;
976
978
 
977
- if (el.clientTop == null) {
978
- clientTop = parseInt(this.getStyle('border-top-width'),0) || 0 ;
979
- } else clientTop = el.clientTop ;
979
+ if (!el.height) {
980
+ clientTop = parseInt(this.getStyle('border-top-width'),0) || 0 ;
981
+ } else clientTop = el.clientTop ;
982
+
983
+ f.x += clientLeft; f.y += clientTop;
984
+ }
985
+ else {
986
+ if (el.clientLeft == null) {
987
+ clientLeft = parseInt(this.getStyle('border-left-width'),0) || 0 ;
988
+ } else clientLeft = el.clientLeft ;
980
989
 
981
- f.x += clientLeft; f.y += clientTop;
990
+ if (el.clientTop == null) {
991
+ clientTop = parseInt(this.getStyle('border-top-width'),0) || 0 ;
992
+ } else clientTop = el.clientTop ;
993
+
994
+ f.x += clientLeft; f.y += clientTop;
995
+ }
982
996
 
983
997
  // cache this frame if using manual layout mode
984
998
  this._innerFrame = SC.cloneRect(f);
985
999
  } else f = SC.cloneRect(this._innerFrame) ;
1000
+ // console.log('returning x:%@ y:%@ w:%@ h:%@'.fmt(f.x, f.y, f.width, f.height));
986
1001
  return f ;
987
1002
  }.property('frame'),
988
1003
 
@@ -1049,7 +1064,8 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
1049
1064
  while(--idx >= 0) {
1050
1065
  padding += parseInt(this.getStyle(SC.View.WIDTH_PADDING_STYLES[idx]), 0) || 0;
1051
1066
  }
1052
- style.width = (Math.floor(f.width) - padding).toString() + 'px' ;
1067
+ var width = Math.floor(f.width) - padding ;
1068
+ if (!isNaN(width)) style.width = width.toString() + 'px' ;
1053
1069
  }
1054
1070
 
1055
1071
  // Resize Height
@@ -1060,7 +1076,8 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
1060
1076
  while(--idx >= 0) {
1061
1077
  padding += parseInt(this.getStyle(SC.View.HEIGHT_PADDING_STYLES[idx]), 0) || 0;
1062
1078
  }
1063
- style.height = (Math.floor(f.height) - padding).toString() + 'px' ;
1079
+ var height = Math.floor(f.height) - padding ;
1080
+ if(!isNaN(height)) style.height = height.toString() + 'px' ;
1064
1081
  }
1065
1082
 
1066
1083
  // now apply style change and clear the cached frame
@@ -1267,14 +1284,40 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
1267
1284
  var f;
1268
1285
  if (this._scrollFrame == null) {
1269
1286
  var el = this.rootElement ;
1270
- f = this._collectFrame(function() {
1271
- return {
1272
- x: 0 - el.scrollLeft,
1273
- y: 0 - el.scrollTop,
1274
- width: el.scrollWidth,
1275
- height: el.scrollHeight
1287
+ var func;
1288
+ if (SC.isIE()) {
1289
+ func = function() {
1290
+ var borderTopWidth = 0;
1291
+ var borderBottomWidth = 0;
1292
+ var borderLeftWidth = 0;
1293
+ var borderRightWidth = 0;
1294
+
1295
+ var overflow = el.currentStyle.overflow;
1296
+ if ( overflow != 'hidden' && overflow != 'auto' ) {
1297
+ borderTopWidth = parseInt(el.currentStyle.borderTopWidth, 0) || 0 ;
1298
+ borderBottomWidth = parseInt(el.currentStyle.borderBottomWidth, 0) || 0 ;
1299
+ borderLeftWidth = parseInt(el.currentStyle.borderLeftWidth, 0) || 0 ;
1300
+ borderRightWidth = parseInt(el.currentStyle.borderRightWidth, 0) || 0 ;
1301
+ }
1302
+ return {
1303
+ x: 0 - el.scrollLeft,
1304
+ y: 0 - el.scrollTop,
1305
+ width: el.scrollWidth + borderLeftWidth + borderRightWidth,
1306
+ height: Math.max(el.scrollHeight, el.clientHeight) + borderTopWidth + borderBottomWidth
1307
+ };
1276
1308
  };
1277
- }) ;
1309
+ }
1310
+ else {
1311
+ func = function() {
1312
+ return {
1313
+ x: 0 - el.scrollLeft,
1314
+ y: 0 - el.scrollTop,
1315
+ width: el.scrollWidth,
1316
+ height: el.scrollHeight
1317
+ };
1318
+ };
1319
+ }
1320
+ f = this._collectFrame(func);
1278
1321
 
1279
1322
  // cache this frame if using manual layout mode
1280
1323
  this._scrollFrame = SC.cloneRect(f);
@@ -2207,18 +2250,15 @@ if (SC.Platform.IE) {
2207
2250
  // case always use the scrollWidth/Height.
2208
2251
  SC.View._collectInnerFrame = function() {
2209
2252
  var el = this.rootElement ;
2210
- var hasLayout = (el.currentStyle) ? el.currentStyle.hasLayout : NO ;
2253
+ var hasLayout = (el.currentStyle) ? el.currentStyle.hasLayout : false ;
2211
2254
  var borderTopWidth = parseInt(el.currentStyle.borderTopWidth, 0) || 0 ;
2212
2255
  var borderBottomWidth = parseInt(el.currentStyle.borderBottomWidth, 0) || 0 ;
2213
- var scrollHeight = el.offsetHeight-borderTopWidth-borderBottomWidth;
2214
- if(el.clientWidth > el.scrollWidth)
2215
- {
2216
- scrollHeight-15;
2217
- }
2256
+ var scrollHeight = el.offsetHeight - borderTopWidth - borderBottomWidth ;
2257
+ if (el.clientWidth > el.scrollWidth) scrollHeight - 15 ;
2218
2258
 
2219
2259
  return {
2220
- x: el.offsetLeft,
2221
- y: el.offsetTop,
2260
+ x: el.offsetLeft,
2261
+ y: el.offsetTop,
2222
2262
  width: (hasLayout) ? Math.min(el.scrollWidth, el.clientWidth) : el.scrollWidth,
2223
2263
  height: (hasLayout) ? Math.min(scrollHeight, el.clientHeight) : scrollHeight
2224
2264
  };
data/lib/sproutcore.rb CHANGED
@@ -21,8 +21,11 @@ module SproutCore
21
21
  end
22
22
 
23
23
  # Force load the code files. Others may be loaded only as required
24
- %w(library bundle bundle_manifest bundle_installer jsdoc jsmin version).each do |fname|
24
+ %w(library bundle bundle_manifest bundle_installer jsdoc jsmin cssmin version).each do |fname|
25
25
  require "sproutcore/#{fname}"
26
26
  end
27
+ %w(erubis haml sass).each do |fname|
28
+ require "sproutcore/renderers/#{fname}"
29
+ end
27
30
 
28
31
  SC= SproutCore
@@ -1,4 +1,3 @@
1
- require 'erubis'
2
1
  require 'sproutcore/helpers'
3
2
  require 'sproutcore/view_helpers'
4
3
 
@@ -17,9 +16,10 @@ module SproutCore
17
16
  include SproutCore::Helpers::TextHelper
18
17
  include SproutCore::Helpers::CaptureHelper
19
18
  include SproutCore::Helpers::StaticHelper
19
+ include SproutCore::Helpers::DomIdHelper
20
20
  include SproutCore::ViewHelpers
21
21
 
22
- attr_reader :entry, :bundle, :entries, :filename, :language, :library
22
+ attr_reader :entry, :bundle, :entries, :filename, :language, :library, :renderer
23
23
 
24
24
  def initialize(entry, bundle, deep=true)
25
25
  @entry = nil
@@ -56,61 +56,65 @@ module SproutCore
56
56
  # Actually builds the HTML file from the entry (actually from any
57
57
  # composite entries)
58
58
  def build
59
-
60
59
  @layout_path = bundle.layout_path
61
60
 
62
- # Render each filename. By default, the output goes to the resources
63
- # string
64
- @content_for_resources = ''
65
- entries.each { |fn| _render_one(fn) }
61
+ # Render each filename. By default, the output goes to the :resources
62
+ # content section
63
+ entries.each do |entry|
64
+ content_for :resources do
65
+ _build_one(entry)
66
+ end
67
+ end
66
68
 
67
69
  # Finally, render the layout. This should produce the final output to
68
70
  # return
69
- input = File.read(@layout_path)
70
-
71
- # render using either erb or haml
72
- case File.extname(@layout_path)
73
- when /\.rhtml$/, /\.html.erb$/
74
- return eval(Erubis::Eruby.new.convert(input))
75
- when /\.haml$/, /\.html.haml$/
76
- require 'haml'
77
- return Haml::Engine.new(input).to_html(self)
78
- end
71
+ _render(@layout_path)
79
72
  end
80
73
 
81
- # render a single entry
82
- def _render_one(entry)
83
- @entry = entry
84
- @filename = @entry.filename
85
-
86
- # avoid double render of layout path
87
- return if @entry.source_path == @layout_path
88
-
89
- # render. Result goes into @content_for_resources
90
- input = File.read(@entry.source_path)
91
-
92
- # render using either erb or haml
93
- case File.extname(@entry.source_path)
94
- when /\.rhtml$/, /\.html.erb$/
95
- @content_for_resources += eval(Erubis::Eruby.new.convert(input))
96
- when /\.haml$/, /\.html.haml$/
97
- require 'haml'
98
- @content_for_resources += Haml::Engine.new(input).to_html(self)
99
- end
100
-
101
- @filename =nil
102
- @entry = nil
103
- end
104
-
105
-
106
74
  # Returns the current bundle name. Often useful for generating titles,
107
75
  # etc.
108
76
  def bundle_name; bundle.bundle_name; end
109
77
 
110
- #### For Rails Compatibility. render() does not do anything useful
111
- # since the new build system is nice about putting things into the right
112
- # place for output.
113
- def render; ''; end
78
+ private
79
+
80
+ # Builds a single entry
81
+ def _build_one(entry)
82
+ # avoid double render of layout path
83
+ return if entry.source_path == @layout_path
84
+
85
+ @entry = entry
86
+ @filename = @entry.filename
87
+ begin
88
+ _render(@entry.source_path)
89
+ ensure
90
+ @filename = nil
91
+ @entry = nil
92
+ end
93
+ end
94
+
95
+ def _render(file_path)
96
+ SC.logger.debug("~ Rendering #{file_path}")
97
+ input = File.read(file_path)
98
+ @renderer = case file_path
99
+ when /\.rhtml$/, /\.html.erb$/
100
+ Sproutcore::Renderers::Erubis.new(self)
101
+ when /\.haml$/
102
+ Sproutcore::Renderers::Haml.new(self)
103
+ end
104
+ _render_compiled_template( @renderer.compile(input) )
105
+ end
106
+
107
+ # Renders a compiled template within this context
108
+ def _render_compiled_template(compiled_template)
109
+ self.instance_eval "def __render(); #{compiled_template}; end"
110
+ begin
111
+ self.send(:__render) do |*names|
112
+ self.instance_variable_get("@content_for_#{names.first}")
113
+ end
114
+ ensure
115
+ class << self; self end.class_eval{ remove_method(:__render) } rescue nil
116
+ end
117
+ end
114
118
 
115
119
  end
116
120