uki 1.1.1 → 1.1.2

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.
Files changed (144) hide show
  1. data/VERSION +1 -1
  2. data/bin/uki +1 -1
  3. data/frameworks/uki/README.rdoc +1 -1
  4. data/frameworks/uki/examples/core-examples/controls/controls.js +6 -6
  5. data/frameworks/uki/examples/core-examples/flow/flow.js +4 -4
  6. data/frameworks/uki/examples/core-examples/linearGradient/gradient.svg +11 -0
  7. data/frameworks/uki/examples/core-examples/linearGradient/linearGradient.js +87 -0
  8. data/frameworks/uki/examples/core-examples/popup/popup.js +23 -10
  9. data/frameworks/uki/examples/core-examples/resizeToContents/resizeToContents.js +12 -1
  10. data/frameworks/uki/examples/core-examples/slider/slider.js +1 -1
  11. data/frameworks/uki/examples/core-examples/splitPaneExtended/splitPaneExtended.js +1 -1
  12. data/frameworks/uki/examples/core-examples/table/table.js +19 -2
  13. data/frameworks/uki/examples/core-examples/wave/wave-theme.js +1 -1
  14. data/frameworks/uki/examples/core-examples/wave/wave.js +1 -1
  15. data/frameworks/uki/examples/more-examples/radioButton/radioButton.js +3 -3
  16. data/frameworks/uki/examples/more-examples/select/select.js +35 -0
  17. data/frameworks/uki/examples/touch-examples/scrollPane/scrollPane.js +53 -0
  18. data/frameworks/uki/spec/unit/background.spec.js +1 -1
  19. data/frameworks/uki/spec/unit/selector.spec.js +28 -12
  20. data/frameworks/uki/spec/unit/utils.spec.js +14 -0
  21. data/frameworks/uki/src/uki-core.js +3 -1
  22. data/frameworks/uki/src/uki-core/after.js +57 -0
  23. data/frameworks/uki/src/uki-core/attachment.js +15 -6
  24. data/frameworks/uki/src/uki-core/background.js +4 -3
  25. data/frameworks/uki/src/uki-core/background/css.js +1 -0
  26. data/frameworks/uki/src/uki-core/background/cssBox.js +5 -3
  27. data/frameworks/uki/src/uki-core/background/linearGradient.js +112 -0
  28. data/frameworks/uki/src/uki-core/background/multi.js +2 -2
  29. data/frameworks/uki/src/uki-core/background/rows.js +1 -0
  30. data/frameworks/uki/src/uki-core/background/sliced9.js +5 -2
  31. data/frameworks/uki/src/uki-core/builder.js +5 -4
  32. data/frameworks/uki/src/uki-core/collection.js +18 -13
  33. data/frameworks/uki/src/uki-core/dom/browser.js +114 -0
  34. data/frameworks/uki/src/uki-core/dom/event.js +3 -0
  35. data/frameworks/uki/src/uki-core/image.js +1 -26
  36. data/frameworks/uki/src/uki-core/selector.js +5 -0
  37. data/frameworks/uki/src/uki-core/theme.js +24 -23
  38. data/frameworks/uki/src/uki-core/theme/template.js +1 -1
  39. data/frameworks/uki/src/uki-core/uki.js +7 -4
  40. data/frameworks/uki/src/uki-core/utils.js +51 -26
  41. data/frameworks/uki/src/uki-core/view.js +6 -3
  42. data/frameworks/uki/src/uki-core/view/base.js +16 -1
  43. data/frameworks/uki/src/uki-core/view/container.js +15 -5
  44. data/frameworks/uki/src/uki-core/view/focusable.js +17 -4
  45. data/frameworks/uki/src/uki-core/view/observable.js +15 -2
  46. data/frameworks/uki/src/uki-core/view/styleable.js +4 -11
  47. data/frameworks/uki/src/uki-data/ajax.js +4 -30
  48. data/frameworks/uki/src/uki-data/json.js +191 -0
  49. data/frameworks/uki/src/uki-data/localStore.js +37 -0
  50. data/frameworks/uki/src/uki-data/model.js +1 -1
  51. data/frameworks/uki/src/uki-more.js +4 -0
  52. data/frameworks/uki/src/uki-more/more/background.js +2 -0
  53. data/frameworks/uki/src/uki-more/more/color.js +168 -0
  54. data/frameworks/uki/src/uki-more/more/utils.js +5 -12
  55. data/frameworks/uki/src/uki-more/more/view.js +3 -1
  56. data/frameworks/uki/src/uki-more/more/view/form.js +30 -0
  57. data/frameworks/uki/src/uki-more/more/view/hTile.js +59 -0
  58. data/frameworks/uki/src/uki-more/more/view/nativeButton.js +3 -0
  59. data/frameworks/uki/src/uki-more/more/view/nativeCheckbox.js +38 -0
  60. data/frameworks/uki/src/uki-more/more/view/nativeControl.js +40 -0
  61. data/frameworks/uki/src/uki-more/more/view/nativeInput.js +78 -0
  62. data/frameworks/uki/src/uki-more/more/view/nativeSelect.js +29 -0
  63. data/frameworks/uki/src/uki-more/more/view/radioButton.js +1 -1
  64. data/frameworks/uki/src/uki-more/more/view/select-theme.js +55 -0
  65. data/frameworks/uki/src/uki-more/more/view/select.js +208 -0
  66. data/frameworks/uki/src/uki-theme/airport.js +145 -88
  67. data/frameworks/uki/src/uki-theme/airport/i/table/a-down.png +0 -0
  68. data/frameworks/uki/src/uki-theme/airport/i/table/a-up.png +0 -0
  69. data/frameworks/uki/src/uki-touch.js +2 -0
  70. data/frameworks/uki/src/uki-touch/touch.js +1 -0
  71. data/frameworks/uki/src/uki-touch/touch/const.js +24 -0
  72. data/frameworks/uki/src/uki-touch/touch/setup.js +52 -0
  73. data/frameworks/uki/src/uki-touch/touch/view.js +4 -0
  74. data/frameworks/uki/src/uki-touch/touch/view/scrollPane.js +505 -0
  75. data/frameworks/uki/src/uki-touch/touch/view/scrollableList.js +27 -0
  76. data/frameworks/uki/src/uki-view/view/box.js +9 -0
  77. data/frameworks/uki/src/uki-view/view/button.js +36 -1
  78. data/frameworks/uki/src/uki-view/view/checkbox.js +32 -3
  79. data/frameworks/uki/src/uki-view/view/flow.js +37 -9
  80. data/frameworks/uki/src/uki-view/view/image.js +14 -1
  81. data/frameworks/uki/src/uki-view/view/label.js +72 -11
  82. data/frameworks/uki/src/uki-view/view/list.js +143 -13
  83. data/frameworks/uki/src/uki-view/view/list/render.js +1 -0
  84. data/frameworks/uki/src/uki-view/view/popup.js +46 -2
  85. data/frameworks/uki/src/uki-view/view/radio.js +19 -4
  86. data/frameworks/uki/src/uki-view/view/scrollPane.js +91 -33
  87. data/frameworks/uki/src/uki-view/view/slider.js +67 -54
  88. data/frameworks/uki/src/uki-view/view/splitPane.js +102 -9
  89. data/frameworks/uki/src/uki-view/view/table.js +59 -2
  90. data/frameworks/uki/src/uki-view/view/table/column.js +45 -17
  91. data/frameworks/uki/src/uki-view/view/table/header.js +40 -12
  92. data/frameworks/uki/src/uki-view/view/table/render.js +4 -0
  93. data/frameworks/uki/src/uki-view/view/textField.js +75 -21
  94. data/frameworks/uki/src/uki-view/view/toolbar.js +16 -0
  95. data/lib/uki/builder.rb +1 -1
  96. data/lib/uki/include_js.rb +2 -2
  97. data/lib/uki/project.rb +14 -14
  98. data/templates/index.html.erb +2 -2
  99. data/templates/myapp.js.erb +2 -2
  100. data/uki.gemspec +34 -48
  101. metadata +44 -47
  102. data/frameworks/uki/src/uki-core/dom/nativeLayout.js +0 -18
  103. data/frameworks/uki/src/uki-theme/airport/i/button/down-c.gif +0 -0
  104. data/frameworks/uki/src/uki-theme/airport/i/button/down-c.png +0 -0
  105. data/frameworks/uki/src/uki-theme/airport/i/button/down-h.gif +0 -0
  106. data/frameworks/uki/src/uki-theme/airport/i/button/down-h.png +0 -0
  107. data/frameworks/uki/src/uki-theme/airport/i/button/down-m.png +0 -0
  108. data/frameworks/uki/src/uki-theme/airport/i/button/down-v.png +0 -0
  109. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-c.png +0 -0
  110. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-h.png +0 -0
  111. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-m.png +0 -0
  112. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-v.png +0 -0
  113. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing.png +0 -0
  114. data/frameworks/uki/src/uki-theme/airport/i/button/hover-c.gif +0 -0
  115. data/frameworks/uki/src/uki-theme/airport/i/button/hover-c.png +0 -0
  116. data/frameworks/uki/src/uki-theme/airport/i/button/hover-h.gif +0 -0
  117. data/frameworks/uki/src/uki-theme/airport/i/button/hover-h.png +0 -0
  118. data/frameworks/uki/src/uki-theme/airport/i/button/hover-m.png +0 -0
  119. data/frameworks/uki/src/uki-theme/airport/i/button/hover-v.png +0 -0
  120. data/frameworks/uki/src/uki-theme/airport/i/button/hover.png +0 -0
  121. data/frameworks/uki/src/uki-theme/airport/i/button/normal-c.gif +0 -0
  122. data/frameworks/uki/src/uki-theme/airport/i/button/normal-c.png +0 -0
  123. data/frameworks/uki/src/uki-theme/airport/i/button/normal-h.gif +0 -0
  124. data/frameworks/uki/src/uki-theme/airport/i/button/normal-h.png +0 -0
  125. data/frameworks/uki/src/uki-theme/airport/i/button/normal-m.png +0 -0
  126. data/frameworks/uki/src/uki-theme/airport/i/button/normal-v.png +0 -0
  127. data/frameworks/uki/src/uki-theme/airport/i/button/normal.png +0 -0
  128. data/frameworks/uki/src/uki-theme/airport/i/panel/dark-h.gif +0 -0
  129. data/frameworks/uki/src/uki-theme/airport/i/panel/dark-h.png +0 -0
  130. data/frameworks/uki/src/uki-theme/airport/i/panel/dark-m.png +0 -0
  131. data/frameworks/uki/src/uki-theme/airport/i/panel/dark.png +0 -0
  132. data/frameworks/uki/src/uki-theme/airport/i/popup/normal.png +0 -0
  133. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-c.png +0 -0
  134. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-h.png +0 -0
  135. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-m.png +0 -0
  136. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-v.png +0 -0
  137. data/frameworks/uki/src/uki-theme/airport/i/shadow/large.png +0 -0
  138. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-m.gif +0 -0
  139. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-m.png +0 -0
  140. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-v.gif +0 -0
  141. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-v.png +0 -0
  142. data/frameworks/uki/src/uki-theme/airport/i/slider/bar.png +0 -0
  143. data/frameworks/uki/src/uki-theme/airport/i/slider/focus.png +0 -0
  144. data/frameworks/uki/src/uki-theme/airport/i/slider/handle.gif +0 -0
@@ -1,5 +1,6 @@
1
1
  include('uki.js');
2
-
2
+ (function() {
3
+
3
4
  var toString = Object.prototype.toString,
4
5
  trim = String.prototype.trim,
5
6
  slice = Array.prototype.slice,
@@ -8,7 +9,10 @@ var toString = Object.prototype.toString,
8
9
 
9
10
  var marked = '__uki_marked';
10
11
 
11
-
12
+ // dummy subclass
13
+ /** @ignore */
14
+ function inheritance () {}
15
+
12
16
  /**
13
17
  * Utility functions.
14
18
  */
@@ -164,7 +168,7 @@ var utils = {
164
168
  array[i][marked] = true;
165
169
  };
166
170
  for (i = 0; i < result.length; i++) {
167
- delete result[i][marked]
171
+ delete result[i][marked];
168
172
  };
169
173
  return result;
170
174
 
@@ -259,13 +263,13 @@ var utils = {
259
263
  */
260
264
  extend: function() {
261
265
  var target = arguments[0] || {}, i = 1, length = arguments.length, options;
262
-
266
+
263
267
  for ( ; i < length; i++ ) {
264
268
  if ( (options = arguments[i]) != null ) {
265
269
 
266
270
  for ( var name in options ) {
267
271
  var copy = options[ name ];
268
-
272
+
269
273
  if ( copy !== undefined ) {
270
274
  target[ name ] = copy;
271
275
  }
@@ -273,7 +277,7 @@ var utils = {
273
277
  }
274
278
  }
275
279
  }
276
-
280
+
277
281
  return target;
278
282
  },
279
283
 
@@ -297,32 +301,37 @@ var utils = {
297
301
  newClass: function(/* [[superClass], mixin1, mixin2, ..] */ methods) {
298
302
  var klass = function() {
299
303
  this.init.apply(this, arguments);
300
- };
304
+ },
301
305
 
302
- var inheritance, i, startFrom = 0, tmp, baseClasses = [], base, name, copy;
303
-
304
- if (arguments.length > 1) {
305
- if (arguments[0].prototype) { // real inheritance
306
- /** @ignore */
307
- inheritance = function() {};
308
- inheritance.prototype = arguments[0].prototype;
306
+ i, startFrom = 0, tmp, baseClasses = [], base, name, copy, $arguments = arguments, length;
307
+
308
+ if ((length = $arguments.length) > 1) {
309
+ base = $arguments[0];
310
+ if (base.prototype) { // real inheritance
311
+ inheritance.prototype = base.prototype;
309
312
  klass.prototype = new inheritance();
310
313
  startFrom = 1;
311
314
  baseClasses = [inheritance.prototype];
315
+
316
+ // class method inheritance
317
+ for ( name in base ) {
318
+ copy = base[ name ];
319
+ if ( !base.hasOwnProperty(name) || copy === undefined || name == 'prototype' ) continue;
320
+ klass[ name ] = copy;
321
+ }
312
322
  }
313
323
  }
314
- for (i=startFrom; i < arguments.length; i++) {
315
- base = tmp = arguments[i];
316
- if (this.isFunction(tmp)) tmp = tmp.apply(tmp, baseClasses);
317
- baseClasses.push(tmp);
318
-
319
- for ( name in base ) {
320
- copy = base[ name ];
321
- if ( !base.hasOwnProperty(name) || copy === undefined ) continue;
322
- klass.prototype[ name ] = copy;
324
+
325
+ for (i=startFrom; i < length; i++) {
326
+ base = $arguments[i];
327
+ if (this.isFunction(base)) {
328
+ tmp = {};
329
+ base.apply(tmp, baseClasses);
330
+ base = tmp;
323
331
  }
332
+ baseClasses[ baseClasses.length ] = base;
324
333
 
325
- // uki.extend(klass.prototype, base);
334
+ uki.extend(klass.prototype, base);
326
335
  };
327
336
  if (!klass.prototype.init) klass.prototype.init = function() {};
328
337
  return klass;
@@ -336,10 +345,12 @@ var utils = {
336
345
  */
337
346
  binarySearch: function (value, array) {
338
347
  var low = 0, high = array.length, mid;
348
+
339
349
  while (low < high) {
340
350
  mid = (low + high) >> 1;
341
351
  array[mid] < value ? low = mid + 1 : high = mid;
342
352
  }
353
+
343
354
  return low;
344
355
  },
345
356
 
@@ -382,7 +393,8 @@ var utils = {
382
393
  * @param {Array.<string>} props Property names
383
394
  */
384
395
  addProps: function(proto, props) {
385
- uki.each(props, function() { proto[this] = uki.newProp('_' + this); });
396
+ for (var i =0, len = props.length; i<len; i++)
397
+ proto[ props[i] ] = uki.newProp('_' + props[i]);
386
398
  },
387
399
 
388
400
  toArray: function(arr) {
@@ -403,7 +415,20 @@ var utils = {
403
415
  }
404
416
  return this;
405
417
  };
418
+ },
419
+
420
+ camalize: function(string) {
421
+ return string.replace(/[-_]\S/g, function(v) {
422
+ return v.substr(1).toUpperCase();
423
+ });
424
+ },
425
+
426
+ dasherize: function(string) {
427
+ return string.replace(/[A-Z]/g, function(v) {
428
+ return '-' + v.toLowerCase();
429
+ });
406
430
  }
407
431
  };
408
432
  utils.extend(uki, utils);
409
- delete utils;
433
+
434
+ })();
@@ -7,15 +7,18 @@ uki.view = {
7
7
  klass = uki.newClass.apply(uki, args),
8
8
  parts = name.split('.'),
9
9
  obj = root,
10
- i, part;
10
+ i, part, l = parts.length - 1;
11
11
 
12
12
  klass.prototype.typeName = function() { return name; };
13
- for ( i=0; i < parts.length - 1; i++ ) {
13
+
14
+ for ( i= 0; i < l; i++ ) {
14
15
  part = parts[i];
15
16
  if (!obj[part]) obj[part] = {};
16
17
  obj = obj[part];
18
+
17
19
  };
18
- obj[parts[parts.length - 1]] = klass;
20
+
21
+ obj[ parts[l] ] = klass;
19
22
  return klass;
20
23
  }
21
24
  };
@@ -3,7 +3,6 @@ include('../geometry.js');
3
3
  include('../utils.js');
4
4
  include('../builder.js');
5
5
  include('../dom.js');
6
- include('../dom/nativeLayout.js');
7
6
  include('observable.js');
8
7
  include('styleable.js');
9
8
 
@@ -274,6 +273,10 @@ uki.view.declare('uki.view.Base', uki.view.Observable, uki.view.Styleable, funct
274
273
  this._firstLayout = false;
275
274
  };
276
275
 
276
+ this.layoutIfNeeded = function() {
277
+ if (this._needsLayout && this.visible()) this.layout();
278
+ };
279
+
277
280
 
278
281
  /**
279
282
  * @function uki.view.Base#minSize
@@ -318,6 +321,13 @@ uki.view.declare('uki.view.Base', uki.view.Observable, uki.view.Styleable, funct
318
321
  this.rect(newRect);
319
322
  };
320
323
 
324
+ /**
325
+ * Called when child changes it's size
326
+ */
327
+ this.childResized = function(child) {
328
+ // do nothing, extend in subviews
329
+ };
330
+
321
331
  /**
322
332
  * Resizes view to its contents. Contents size is determined by view.
323
333
  * View can be resized by width, height or both. This is specified through
@@ -442,6 +452,11 @@ uki.view.declare('uki.view.Base', uki.view.Observable, uki.view.Styleable, funct
442
452
  */
443
453
  this._createDom = function() {
444
454
  this._dom = uki.createElement('div', this.defaultCss);
455
+ this._initClassName();
456
+ };
457
+
458
+ this._initClassName = function() {
459
+ this._dom.className = this.typeName().replace(/\./g, '-');
445
460
  };
446
461
 
447
462
  /**
@@ -8,6 +8,8 @@ include('base.js');
8
8
  uki.view.declare('uki.view.Container', uki.view.Base, function(Base) {
9
9
  /**#@+ @memberOf uki.view.Container# */
10
10
 
11
+ this._inset = new Inset();
12
+
11
13
  /** @private */
12
14
  this._setup = function() {
13
15
  this._childViews = [];
@@ -25,11 +27,11 @@ uki.view.declare('uki.view.Container', uki.view.Base, function(Base) {
25
27
  }
26
28
 
27
29
  this.contentsWidth = function() {
28
- return maxProp(this, 'maxX');
30
+ return maxProp(this, 'maxX') + this.inset().right;
29
31
  };
30
32
 
31
33
  this.contentsHeight = function() {
32
- return maxProp(this, 'maxY');
34
+ return maxProp(this, 'maxY') + this.inset().bottom;
33
35
  };
34
36
 
35
37
  this.contentsSize = function() {
@@ -65,6 +67,7 @@ uki.view.declare('uki.view.Container', uki.view.Base, function(Base) {
65
67
  this._childViews[i]._viewIndex--;
66
68
  };
67
69
  this._childViews = uki.grep(this._childViews, function(elem) { return elem != child; });
70
+ this._contentChanged();
68
71
  };
69
72
 
70
73
  /**
@@ -75,6 +78,7 @@ uki.view.declare('uki.view.Container', uki.view.Base, function(Base) {
75
78
  this._childViews.push(child);
76
79
  child.parent(this);
77
80
  this.domForChild(child).appendChild(child.dom());
81
+ this._contentChanged();
78
82
  };
79
83
 
80
84
  /**
@@ -91,6 +95,7 @@ uki.view.declare('uki.view.Container', uki.view.Base, function(Base) {
91
95
  this._childViews.splice(beforeChild._viewIndex-1, 0, child);
92
96
  child.parent(this);
93
97
  this.domForChild(child).insertBefore(child.dom(), beforeChild.dom());
98
+ this._contentChanged();
94
99
  };
95
100
 
96
101
  /**
@@ -101,8 +106,15 @@ uki.view.declare('uki.view.Container', uki.view.Base, function(Base) {
101
106
  return this._dom;
102
107
  };
103
108
 
109
+ this.inset = uki.newProp('_inset', function(v) {
110
+ this._inset = Inset.create(v);
111
+ });
104
112
 
105
113
  /** @private */
114
+ this._contentChanged = function() {
115
+ // called on every insertBefore, appendChild, removeChild
116
+ };
117
+
106
118
  this._layoutDom = function(rect) {
107
119
  Base._layoutDom.call(this, rect);
108
120
  this._layoutChildViews(rect);
@@ -111,9 +123,7 @@ uki.view.declare('uki.view.Container', uki.view.Base, function(Base) {
111
123
  /** @private */
112
124
  this._layoutChildViews = function() {
113
125
  for (var i=0, childViews = this.childViews(); i < childViews.length; i++) {
114
- if (childViews[i]._needsLayout && childViews[i].visible()) {
115
- childViews[i].layout(this._rect);
116
- }
126
+ childViews[i].layoutIfNeeded();
117
127
  };
118
128
  };
119
129
 
@@ -2,7 +2,7 @@ include('../view.js');
2
2
  include('observable.js');
3
3
 
4
4
  /**
5
- * @class
5
+ * @interface
6
6
  */
7
7
  uki.view.Focusable = new function() {/** @lends uki.view.Focusable.prototype */
8
8
 
@@ -45,21 +45,25 @@ uki.view.Focusable = new function() {/** @lends uki.view.Focusable.prototype */
45
45
 
46
46
  if (!preCreatedFocusTarget) {
47
47
  this._focusTarget = uki.createElement('input', 'position:absolute;left:-9999px;top:0;width:1px;height:1px;');
48
+ this._focusTarget.className = 'uki-view-Focusable';
48
49
  this.dom().appendChild(this._focusTarget);
49
50
  }
50
51
  this._hasFocus = false;
51
52
  this._firstFocus = true;
52
53
 
53
54
  uki.dom.bind(this._focusTarget, 'focus', uki.proxy(function(e) {
55
+ this._stopWatingForBlur();
54
56
  if (!this._hasFocus) this._focus(e);
55
57
  }, this));
56
58
 
57
59
  uki.dom.bind(this._focusTarget, 'blur', uki.proxy(function(e) {
58
60
  if (this._hasFocus) {
59
61
  this._hasFocus = false;
60
- setTimeout(uki.proxy(function() { // wait for mousedown refocusing
61
- if (!this._hasFocus) this._blur();
62
- }, this), 1);
62
+ this._waitingForBlur =
63
+ setTimeout(uki.proxy(function() { // wait for mousedown refocusing
64
+ this._waitingForBlur = false;
65
+ if (!this._hasFocus) this._blur();
66
+ }, this), 1);
63
67
  }
64
68
  }, this));
65
69
 
@@ -78,8 +82,17 @@ uki.view.Focusable = new function() {/** @lends uki.view.Focusable.prototype */
78
82
  this._hasFocus = false;
79
83
  }
80
84
 
85
+ this._stopWatingForBlur = function() {
86
+ if (this._waitingForBlur) {
87
+ clearTimeout(this._waitingForBlur);
88
+ this._waitingForBlur = false;
89
+ this._hasFocus = true;
90
+ }
91
+ };
92
+
81
93
  this.focus = function() {
82
94
  if (this._focusable && !this._disabled) {
95
+ this._stopWatingForBlur();
83
96
  if (!this._hasFocus) this._focus();
84
97
  var target = this._focusTarget;
85
98
  setTimeout(function() {
@@ -8,6 +8,10 @@ uki.view.Observable = /** @lends uki.view.Observable.prototype */ {
8
8
  // return null; // should implement
9
9
  // },
10
10
 
11
+ /**
12
+ * @param {String} name Event name
13
+ * @param {function()} callback
14
+ */
11
15
  bind: function(name, callback) {
12
16
  callback.huid = callback.huid || uki.guid++;
13
17
  uki.each(name.split(' '), function(i, name) {
@@ -18,11 +22,20 @@ uki.view.Observable = /** @lends uki.view.Observable.prototype */ {
18
22
  },
19
23
 
20
24
  unbind: function(name, callback) {
21
- uki.each(name.split(' '), function(i, name) {
25
+ if (!this._observers) return;
26
+ var names;
27
+ if (name) {
28
+ names = name.split(' ');
29
+ } else {
30
+ names = [];
31
+ uki.each(this._observers, function(k, v) { names.push(k) });
32
+ }
33
+ uki.each(names, function(i, name) {
22
34
  this._observers[name] = !callback ? [] : uki.grep(this._observersFor(name, true), function(observer) {
23
35
  return observer != callback && observer.huid != callback.huid;
24
36
  });
25
37
  if (this._observers[name].length == 0) {
38
+ this._observers[name] = undefined;
26
39
  this._unbindFromDom(name);
27
40
  }
28
41
  }, this);
@@ -43,7 +56,7 @@ uki.view.Observable = /** @lends uki.view.Observable.prototype */ {
43
56
  },
44
57
 
45
58
  _bindToDom: function(name, target) {
46
- if (!target && !this.dom) return;
59
+ if (!target && !this.dom) return false;
47
60
  this._domHander = this._domHander || uki.proxy(function(e) {
48
61
  e.source = this;
49
62
  this.trigger(e.type, e);
@@ -33,11 +33,6 @@ uki.view.Styleable = new function() {
33
33
  // };
34
34
  // });
35
35
 
36
- var probe = uki.createElement('div').style;
37
- uki.each(['userSelect', 'MozUserSelect', 'WebkitUserSelect'], function(i, name) {
38
- if (typeof probe[name] == 'string') this._textSelectProp = name;
39
- }, this);
40
-
41
36
  /**
42
37
  * Sets whether text of the view can be selected.
43
38
  *
@@ -47,17 +42,15 @@ uki.view.Styleable = new function() {
47
42
  * @param {boolean=} state
48
43
  * @returns {boolean|uki.view.Base} current textSelectable state of self
49
44
  */
50
- this.textSelectable = function(state) {
51
- if (state === undefined) return this._textSelectable;
45
+ this.textSelectable = uki.newProp('_textSelectable', function(state) {
52
46
  this._textSelectable = state;
53
- if (this._textSelectProp) {
54
- this._dom.style[this._textSelectProp] = state ? '' : this._textSelectProp == 'MozUserSelect' ? '-moz-none' : 'none';
47
+ if (uki.browser.cssUserSelect() != 'unsupported') {
48
+ this._dom.style[uki.camalize(uki.browser.cssUserSelect())] = (state ? '' : uki.browser.cssUserSelect() == '-moz-user-select' ? '-moz-none' : 'none');
55
49
  } else {
56
50
  uki.dom[state ? 'unbind' : 'bind'](this.dom(), 'selectstart', uki.dom.preventDefaultHandler);
57
51
  }
58
52
  this._dom.style.cursor = state ? '' : 'default';
59
- return this;
60
- };
53
+ });
61
54
 
62
55
  this.draggable = function(state) {
63
56
  if (state === undefined) return this._dom.getAttribute('draggable');
@@ -1,3 +1,5 @@
1
+ include('json.js');
2
+
1
3
  /**
2
4
  * based on http://github.com/uki/uki/blob/1.4.2/src/ajax.js
3
5
  *
@@ -18,34 +20,6 @@ var jsc = +new Date,
18
20
 
19
21
 
20
22
  uki.extend(uki, {
21
- error: function( msg ) {
22
- throw msg;
23
- },
24
-
25
- parseJSON: function( data ) {
26
- if ( typeof data !== "string" || !data ) {
27
- return null;
28
- }
29
-
30
- // Make sure leading/trailing whitespace is removed (IE can't handle it)
31
- data = uki.trim( data );
32
-
33
- // Make sure the incoming data is actual JSON
34
- // Logic borrowed from http://json.org/json2.js
35
- if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
36
- .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
37
- .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
38
-
39
- // Try to use the native JSON parser first
40
- return window.JSON && window.JSON.parse ?
41
- window.JSON.parse( data ) :
42
- (new Function("return " + data))();
43
-
44
- } else {
45
- uki.error( "Invalid JSON: " + data );
46
- }
47
- },
48
-
49
23
  // Evalulates a script in a global context
50
24
  globalEval: function( data ) {
51
25
  if ( data && rnotwhite.test(data) ) {
@@ -240,7 +214,7 @@ uki.extend(uki, {
240
214
  }
241
215
 
242
216
  if ( s.cache === false && type === "GET" ) {
243
- var ts = now();
217
+ var ts = +new Date;
244
218
 
245
219
  // try replacing _= if it is there
246
220
  var ret = s.url.replace(rts, "$1_=" + ts + "$2");
@@ -517,7 +491,7 @@ uki.extend(uki, {
517
491
  data = xml ? xhr.responseXML : xhr.responseText;
518
492
 
519
493
  if ( xml && data.documentElement.nodeName === "parsererror" ) {
520
- uki.error( "parsererror" );
494
+ throw "parsererror";
521
495
  }
522
496
 
523
497
  // Allow a pre-filtering function to sanitize the response