rsence-pre 2.1.0.21 → 2.1.8.0

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 (43) hide show
  1. data/INSTALL.rdoc +61 -46
  2. data/README.rdoc +17 -1
  3. data/VERSION +1 -1
  4. data/conf/rsence_command_strings.yaml +16 -16
  5. data/js/comm/sessionwatcher/sessionwatcher.js +5 -4
  6. data/js/comm/transporter/transporter.js +62 -4
  7. data/js/comm/values/values.js +62 -0
  8. data/js/controls/button/themes/default/button.css +7 -7
  9. data/js/controls/imageview/imageview.js +15 -6
  10. data/js/controls/stringview/stringview.js +16 -2
  11. data/js/controls/textcontrol/textcontrol.js +56 -3
  12. data/js/core/elem/elem.js +38 -12
  13. data/js/datetime/timesheet/timesheet.js +141 -32
  14. data/js/datetime/timesheet_item/timesheet_item.js +82 -22
  15. data/js/foundation/application/application.js +10 -4
  16. data/js/foundation/control/control.js +5 -3
  17. data/js/foundation/control/dyncontrol/dyncontrol.js +17 -3
  18. data/js/foundation/control/eventresponder/eventresponder.js +31 -2
  19. data/js/foundation/eventmanager/eventmanager.js +202 -74
  20. data/js/foundation/json_renderer/json_renderer.js +5 -2
  21. data/js/foundation/system/system.js +13 -11
  22. data/js/foundation/view/morphanimation/morphanimation.js +9 -5
  23. data/js/foundation/view/view.js +22 -10
  24. data/js/lists/propertylist/propertylist.js +5 -0
  25. data/js/menus/minimenu/minimenu.js +3 -8
  26. data/lib/conf/default.rb +0 -3
  27. data/lib/http/broker.rb +6 -5
  28. data/lib/http/rackup.rb +3 -3
  29. data/lib/http/response.rb +28 -2
  30. data/lib/session/msg.rb +30 -18
  31. data/lib/transporter/transporter.rb +4 -0
  32. data/lib/values/hvalue.rb +4 -134
  33. data/lib/values/valuemanager.rb +36 -22
  34. data/plugins/client_pkg/lib/client_pkg_serve.rb +195 -152
  35. data/plugins/main/main.rb +8 -10
  36. data/plugins/ticket/lib/common.rb +4 -4
  37. data/plugins/ticket/lib/favicon.rb +1 -1
  38. data/plugins/ticket/lib/rsrc.rb +1 -1
  39. data/plugins/ticket/lib/upload.rb +2 -2
  40. data/plugins/ticket/ticket.rb +3 -3
  41. data/setup/welcome/gui/welcome.yaml +1 -1
  42. metadata +10 -11
  43. data/lib/util/ruby19_fixes.rb +0 -18
@@ -32,10 +32,13 @@ HImageView = HControl.extend({
32
32
  })),
33
33
 
34
34
  _makeScaleToFit: function(_parentId){
35
- this.elemId = ELEM.make(_parentId,'img');
36
- ELEM.setAttr(this.elemId,'src',this.getImgSrc());
37
- ELEM.setAttr(this.elemId,'alt',this.label);
38
- ELEM.setAttr(this.elemId,'title',this.label);
35
+ this.elemId = ELEM.make( _parentId, 'img', {
36
+ attrs: [
37
+ [ 'src', this.getImgSrc() ],
38
+ [ 'alt', this.label ],
39
+ [ 'title', this.label ]
40
+ ]
41
+ } );
39
42
  },
40
43
  _makeScaleToOriginal: function(_parentId){
41
44
  this.elemId = ELEM.make(_parentId,'div');
@@ -58,11 +61,17 @@ HImageView = HControl.extend({
58
61
  *
59
62
  **/
60
63
  refreshValue: function(){
64
+ var _src = this.getImgSrc();
61
65
  if(this.options.scaleToFit){
62
- ELEM.setAttr(this.elemId,'src',this.getImgSrc());
66
+ if(ELEM.getAttr(this.elemId,'src')!==_src){
67
+ ELEM.setAttr(this.elemId,'src',_src);
68
+ }
63
69
  }
64
70
  else{
65
- ELEM.setStyle(this.elemId,'background-image','url('+this.getImgSrc()+')');
71
+ var _url = 'url('+this.getImgSrc()+')';
72
+ if(ELEM.getStyle(this.elemId,'background-image') != _url){
73
+ ELEM.setStyle(this.elemId,'background-image',_url);
74
+ }
66
75
  }
67
76
  },
68
77
 
@@ -22,8 +22,21 @@ HStringView = HControl.extend({
22
22
 
23
23
  componentName: "stringview",
24
24
 
25
+ defaultEvents: {
26
+ contextMenu: true
27
+ },
28
+
29
+ /** = Description
30
+ * HStringView allows the default contextMenu action.
31
+ *
32
+ **/
33
+ contextMenu: function(){
34
+ return true;
35
+ },
36
+
25
37
  /** = Description
26
- * setStyle function
38
+ * The setStyle method of HStringView applies only to the value
39
+ * element (not the whole component).
27
40
  *
28
41
  **/
29
42
  setStyle: function(_name, _value, _cacheOverride) {
@@ -35,7 +48,8 @@ HStringView = HControl.extend({
35
48
  },
36
49
 
37
50
  /** = Description
38
- * refreshLable function
51
+ * The refreshLabel of HStringView sets a tool tip.
52
+ * Applied by the setLabel method and the label attribute of options.
39
53
  *
40
54
  **/
41
55
  refreshLabel: function() {
@@ -22,7 +22,8 @@ HTextControl = HControl.extend({
22
22
  componentName: "textcontrol",
23
23
 
24
24
  defaultEvents: {
25
- textEnter: true
25
+ textEnter: true,
26
+ contextMenu: true
26
27
  },
27
28
 
28
29
  controlDefaults: (HControlDefaults.extend({
@@ -30,6 +31,13 @@ HTextControl = HControl.extend({
30
31
  refreshOnInput: true
31
32
  })),
32
33
 
34
+ /** = Description
35
+ * The contextMenu event for text input components is not prevented by default.
36
+ **/
37
+ contextMenu: function(){
38
+ return true;
39
+ },
40
+
33
41
  /** = Description
34
42
  * The refreshLabel method sets the title property of the text
35
43
  * field, essentially creating a tooltip using the label.
@@ -60,7 +68,49 @@ HTextControl = HControl.extend({
60
68
  /** This flag is true, when the text input field has focus.
61
69
  **/
62
70
  hasTextFocus: false,
63
-
71
+
72
+ _getChangeEventFn: function(){
73
+ var _this = this;
74
+ return function(e){
75
+ _this.setValue(
76
+ _this.validateText(
77
+ _this.getTextFieldValue()
78
+ )
79
+ );
80
+ if(e.type === 'paste'){
81
+ console.log('event: paste, e:', e);
82
+ if(_this._clipboardPasteTimer){
83
+ clearTimeout( this._clipboardPasteTimer );
84
+ }
85
+ this._clipboardPasteTimer = setTimeout( function(){_this.clipboardPaste();}, 200 );
86
+ }
87
+ return true;
88
+ };
89
+ },
90
+
91
+ _clipboardPasteTimer: null,
92
+ clipboardPaste: function(){
93
+ clearTimeout( this._clipboardPasteTimer ); this._clipboardPasteTimer = null;
94
+ console.log('paste event, value now:',this.value);
95
+ },
96
+
97
+ _changeEventFn: null,
98
+ _clearChangeEventFn: function(){
99
+ if( this._changeEventFn ){
100
+ Event.stopObserving( ELEM.get(this.markupElemIds.value), 'change', this._changeEventFn );
101
+ Event.stopObserving( ELEM.get(this.markupElemIds.value), 'paste', this._changeEventFn );
102
+ this._changeEventFn = null;
103
+ }
104
+ },
105
+ _setChangeEventFn: function(){
106
+ if( this._changeEventFn ){
107
+ this._clearChangeEventFn();
108
+ }
109
+ this._changeEventFn = this._getChangeEventFn();
110
+ Event.observe( ELEM.get(this.markupElemIds.value), 'change', this._changeEventFn );
111
+ Event.observe( ELEM.get(this.markupElemIds.value), 'paste', this._changeEventFn );
112
+ },
113
+
64
114
  /** = Description
65
115
  * Special event for text entry components.
66
116
  * Called when the input field gains focus.
@@ -68,6 +118,7 @@ HTextControl = HControl.extend({
68
118
  **/
69
119
  textFocus: function(){
70
120
  this.hasTextFocus = true;
121
+ this._setChangeEventFn();
71
122
  return true;
72
123
  },
73
124
 
@@ -78,6 +129,7 @@ HTextControl = HControl.extend({
78
129
  **/
79
130
  textBlur: function(){
80
131
  this.hasTextFocus = false;
132
+ this._clearChangeEventFn();
81
133
  if(this.options.refreshOnBlur){
82
134
  this.refreshValue();
83
135
  }
@@ -283,7 +335,8 @@ HNumericTextControl = HTextControl.extend({
283
335
 
284
336
  defaultEvents: {
285
337
  mouseWheel: true,
286
- textEnter: true
338
+ textEnter: true,
339
+ contextMenu: true
287
340
  },
288
341
 
289
342
  /** Uses the mouseWheel event to step up/down the value.
data/js/core/elem/elem.js CHANGED
@@ -12,6 +12,12 @@
12
12
  var//RSence.Core
13
13
  BROWSER_TYPE = {
14
14
 
15
+ /* Any browser on Mac OS X */
16
+ mac: false,
17
+
18
+ /* Any browser on Windows */
19
+ win: false,
20
+
15
21
  /* Any version of Microsoft Internet Explorer */
16
22
  ie: false,
17
23
 
@@ -774,7 +780,6 @@ ELEM = {
774
780
  _key = _currTodo.pop();
775
781
  _val = _attrCache[_key];
776
782
  _elem.setAttribute(_key, _val);
777
- //_elem[_key]=_val;
778
783
  }
779
784
  },
780
785
 
@@ -827,7 +832,7 @@ ELEM = {
827
832
  _attrTodo = _this._attrTodo[_id],
828
833
  _attrCache = _this._attrCache[_id],
829
834
  _differs = _value !== _this.getAttr(_id, _key);
830
- if (_differs) {
835
+ if (_differs || _bypass) {
831
836
  _attrCache[_key] = _value;
832
837
  if (_bypass) {
833
838
  _this._elements[_id].setAttribute(_key, _value);
@@ -1043,11 +1048,15 @@ ELEM = {
1043
1048
  * +_tagName+:: The tag name of the element.
1044
1049
  * (Optional, default: 'DIV')
1045
1050
  *
1051
+ * +_options+:: Options to set before appending child to parent.
1052
+ * Supported option attrs: [[key,value],[key,value]]
1053
+ * (Optional, rarely necessary except when creating IMG tags)
1054
+ *
1046
1055
  * = Returns
1047
1056
  * The new ELEM ID.
1048
1057
  *
1049
1058
  **/
1050
- make: function(_targetId, _tagName) {
1059
+ make: function(_targetId, _tagName, _options) {
1051
1060
  if (_targetId === undefined) {
1052
1061
  _targetId = 0;
1053
1062
  }
@@ -1084,9 +1093,22 @@ ELEM = {
1084
1093
  }
1085
1094
  }
1086
1095
  _elem = document.createElement(_tagName);
1087
- _this._elements[_targetId].appendChild(_elem);
1088
1096
  _id = _this._add(_elem);
1089
1097
  _this._initCache(_id);
1098
+ if(_options!==undefined){
1099
+ if(_options.attrs){
1100
+ var
1101
+ i = 0,
1102
+ _key, _value;
1103
+ for( ; i<_options.attrs.length; i++ ){
1104
+ _key = _options.attrs[i][0];
1105
+ _value = _options.attrs[i][1];
1106
+ _elem[_key] = _value;
1107
+ _this.setAttr( _id, _key, _value );
1108
+ }
1109
+ }
1110
+ }
1111
+ _this._elements[_targetId].appendChild(_elem);
1090
1112
  return _id;
1091
1113
  },
1092
1114
 
@@ -1258,10 +1280,11 @@ ELEM = {
1258
1280
 
1259
1281
  /* Checks browser versions and starts the document load check */
1260
1282
  _warmup: function() {
1261
- var _this = ELEM,
1262
- _ua = navigator.userAgent,
1263
- _isIE = (document.all && (_ua.indexOf("Opera") === -1)),
1264
- _browserType = BROWSER_TYPE;
1283
+ var
1284
+ _this = ELEM,
1285
+ _ua = navigator.userAgent,
1286
+ _isIE = (document.all && (_ua.indexOf("Opera") === -1)),
1287
+ _browserType = BROWSER_TYPE;
1265
1288
  _browserType.opera = _ua.indexOf("Opera") !== -1;
1266
1289
  _browserType.safari = _ua.indexOf("KHTML") !== -1;
1267
1290
  _browserType.symbian = _ua.indexOf("SymbianOS") !== -1;
@@ -1272,6 +1295,9 @@ ELEM = {
1272
1295
  _browserType.ie8 = _isIE && (_ua.indexOf("MSIE 8") !== -1);
1273
1296
  _browserType.ie9 = _isIE && (_ua.indexOf("MSIE 9") !== -1);
1274
1297
 
1298
+ _browserType.mac = (_ua.indexOf("Macintosh") !== -1);
1299
+ _browserType.win = (_ua.indexOf("Windows") !== -1);
1300
+
1275
1301
  // Experimental; don't treat IE9 as an IE at all.
1276
1302
  // NOTE: IE9 Beta does still not behave like a standard web browser.
1277
1303
  // It will probably require as much tuning as earlier IE versions.
@@ -1316,9 +1342,9 @@ ELEM = {
1316
1342
  var _ie_script = document.getElementById("__ie_onload");
1317
1343
  _ie_script.onreadystatechange = function() {
1318
1344
  if ((this.readyState === "complete") && true) {
1319
- clearTimeout(ELEM._domLoadTimer);
1320
- ELEM._domLoadStatus = true;
1321
- ELEM._init();
1345
+ clearTimeout(_this._domLoadTimer);
1346
+ _this._domLoadStatus = true;
1347
+ _this._init();
1322
1348
  }
1323
1349
  };
1324
1350
  // the event will trigger on ie, so we don't have to keep on polling:
@@ -1353,7 +1379,7 @@ ELEM = {
1353
1379
  _this._init();
1354
1380
  }
1355
1381
  else {
1356
- _this._domLoadTimer = setTimeout('ELEM._domWaiter()', _this.ELEMTickerInterval * 10);
1382
+ _this._domLoadTimer = setTimeout(_this._domWaiter, 10 ); // (_this.ELEMTickerInterval * 10));
1357
1383
  }
1358
1384
  }
1359
1385
  };
@@ -11,10 +11,41 @@
11
11
  ***/
12
12
  var//RSence.DateTime
13
13
  HTimeSheet = HControl.extend({
14
+
14
15
  componentName: 'timesheet',
16
+
17
+ /* Default amount of pixels per hour. Override with options when necessary. */
15
18
  pxPerHour: 24,
19
+
20
+ /* Default amount of pixels from left. Override with options when necessary. */
16
21
  itemOffsetLeft: 36,
22
+
23
+ /* Default amount of pixels from right. Override with options when necessary. */
17
24
  itemOffsetRight: 0,
25
+
26
+ defaultEvents: {
27
+ draggable: true
28
+ },
29
+
30
+ controlDefaults: HControlDefaults.extend({
31
+ pxPerHour: null,
32
+ itemOffsetLeft: null,
33
+ itemOffsetRight: null,
34
+ itemMinHeight: 24,
35
+ newItemLabel: 'New Item',
36
+ constructor: function(_ctrl){
37
+ if(this.pxPerHour !== null){
38
+ _ctrl.pxPerHour = this.pxPerHour;
39
+ }
40
+ if(this.itemOffsetLeft !== null){
41
+ _ctrl.itemOffsetLeft = this.itemOffsetLeft;
42
+ }
43
+ if(this.itemOffsetRight !== null){
44
+ _ctrl.itemOffsetRight = this.itemOffsetRight;
45
+ }
46
+ }
47
+ }),
48
+
18
49
  /** = Description
19
50
  * Redraws the timesheet.
20
51
  *
@@ -82,16 +113,7 @@ HTimeSheet = HControl.extend({
82
113
  if(origY>maxY){
83
114
  origY = maxY;
84
115
  }
85
- var item = HTimeSheetItem.nu(
86
- this.createItemRect(origY,lineHeight),
87
- this, {
88
- label: 'New Item',
89
- events: {
90
- draggable: true
91
- }
92
- }
93
- );
94
- this.dragItem = item;
116
+ this.dragItem = this.createTimeSheetItem( { label: this.options.newItemLabel }, origY, lineHeight, 'create' );
95
117
  },
96
118
 
97
119
  /** = Description
@@ -103,9 +125,29 @@ HTimeSheet = HControl.extend({
103
125
  *
104
126
  **/
105
127
  startDrag: function(x,y){
106
- this.createItem(y-this.pageY());
107
- EVENT.startDragging( this.dragItem );
128
+ this._startDragTime = new Date().getTime();
129
+ this._startDragCoords = [x,y];
130
+ return true;
108
131
  },
132
+
133
+ drag: function(x,y){
134
+ if(((new Date().getTime()) - this._startDragTime) < 200){
135
+ // only create when 200 ms has elapsed to enable clicking
136
+ return true;
137
+ }
138
+ if(this._startDragCoords[0]!==x && this._startDragCoords[1]!==y){
139
+ this.createItem(this._startDragCoords[1]-this.pageY());
140
+ EVENT.startDragging( this.dragItem );
141
+ return true;
142
+ }
143
+ },
144
+
145
+ click: function(x,y){
146
+ // deactivate all items
147
+ EVENT.changeActiveControl(this);
148
+ return true;
149
+ },
150
+
109
151
  listItemViews: false,
110
152
 
111
153
  /** = Description
@@ -128,10 +170,13 @@ HTimeSheet = HControl.extend({
128
170
  *
129
171
  **/
130
172
  createItemRect: function(_origY, _lineHeight){
131
- var _left = this.itemOffsetLeft,
132
- _top = _origY,
133
- _right = this.rect.width - this.itemOffsetRight,
134
- _bottom = _origY + _lineHeight;
173
+ var _left = this.itemOffsetLeft+1,
174
+ _top = _origY+1,
175
+ _right = this.rect.width - this.itemOffsetRight - 1,
176
+ _bottom = _origY + _lineHeight - 2;
177
+ if( (_top - _bottom) < this.options.itemMinHeight ){
178
+ _bottom = _top + this.options.itemMinHeight;
179
+ }
135
180
  return HRect.nu( _left, _top, _right, _bottom );
136
181
  },
137
182
 
@@ -144,40 +189,104 @@ HTimeSheet = HControl.extend({
144
189
  this.base();
145
190
  },
146
191
 
192
+ /** = Description
193
+ * Returns a new time sheet item control. By default returns an instance
194
+ * of HTimeSheetItem. Extend to use custom time sheet controls customized
195
+ * for application specific purposes.
196
+ *
197
+ * = Parameters
198
+ * *_value*:: A value object for the item.
199
+ * *_top*:: Top position, 0 by default.
200
+ * *_height*:: Height, same as half of +#pxPerHour+ by default.
201
+ * *_drogMode*:: Dragging mode. 'normal' or 'create'. Is 'normal' by default.
202
+ *
203
+ **/
204
+ createTimeSheetItem: function( _value, _top, _height, _dragMode ) {
205
+ if(_dragMode===undefined){
206
+ _dragMode = 'normal';
207
+ }
208
+ if(_top===undefined){
209
+ _top = 0;
210
+ }
211
+ if(_height===undefined){
212
+ _height = Math.round(this.pxPerHour/2);
213
+ }
214
+ var
215
+ _label = _value['label'],
216
+ _item = HTimeSheetItem.nu(
217
+ this.createItemRect( _top, _height ),
218
+ this, {
219
+ label: _label,
220
+ value: _value,
221
+ events: {
222
+ draggable: true
223
+ }
224
+ }
225
+ );
226
+ _item.dragMode = _dragMode;
227
+ return _item;
228
+ },
229
+
147
230
  /** = Description
148
231
  * Redraws and refreshes the values on timesheet.
149
232
  *
150
233
  **/
151
234
  refreshValue: function(){
152
- var _data = this.value, i;
235
+ var
236
+ _data = this.value,
237
+ i;
153
238
  if(this.listItemViews === false){
154
239
  this.listItemViews = [];
155
240
  }
156
- if(this.listItemViews.length !== 0){
241
+ else if(this.listItemViews.length > 0){
157
242
  for( i=0; i<this.listItemViews.length; i++){
158
243
  this.listItemViews[i].die();
159
244
  }
160
245
  this.listItemViews = [];
161
246
  }
162
- if(_data instanceof Array){
163
- var _value, _label, _item;
247
+ if(_data instanceof Array && _data.length > 0){
248
+ var
249
+ _value,
250
+ _item;
164
251
  for( i=0; i<_data.length; i++){
165
252
  _value = _data[i];
166
- _label = _value['label'];
167
- _item = HTimeSheetItem.nu(
168
- this.createItemRect( 0, 12 ),
169
- this, {
170
- label: _label,
171
- value: _value,
172
- events: {
173
- draggable: true
174
- }
175
- }
176
- );
177
- _item.dragMode = 'normal';
253
+ _item = this.createTimeSheetItem( _value );
178
254
  this.listItemViews.push( _item );
179
255
  }
180
256
  }
257
+ var
258
+ _overlaps = [],
259
+ j;
260
+ for(i=0;i<this.listItemViews.length;i++){
261
+ for(j=0;j<this.listItemViews.length;j++){
262
+ if((i !== j) && (_overlaps.indexOf(i)===-1) && (_overlaps.indexOf(j)===-1)){
263
+ if(this.listItemViews[i].rect.intersects(this.listItemViews[j].rect)){
264
+ _overlaps.push(i);
265
+ }
266
+ }
267
+ }
268
+ }
269
+ var
270
+ _overlapCount = _overlaps.length+1,
271
+ _overlapLefts = {},
272
+ _itemWidth = ( this.rect.width - this.itemOffsetRight - this.itemOffsetLeft ),
273
+ _width = Math.floor( _itemWidth / _overlapCount),
274
+ _left = this.itemOffsetLeft;
275
+ for(j=0;j<_overlapCount;j++){
276
+ _overlapLefts[_overlaps[j]] = _left + (j*_width) + _width;
277
+ }
278
+ for(i=0;i<this.listItemViews.length;i++){
279
+ if(_overlaps.indexOf(i)===-1){
280
+ this.listItemViews[i].rect.setLeft(_left);
281
+ }
282
+ else {
283
+ this.listItemViews[i].rect.setLeft(_overlapLefts[i]);
284
+ }
285
+ this.listItemViews[i].rect.setWidth(_width);
286
+ }
287
+ for(i=0;i<this.listItemViews.length;i++){
288
+ this.listItemViews[i].drawRect();
289
+ }
181
290
  }
182
291
  });
183
292
 
@@ -11,11 +11,31 @@
11
11
  ***/
12
12
  var//RSence.DateTime
13
13
  HTimeSheetItem = HControl.extend({
14
+
14
15
  componentName: 'timesheet_item',
16
+
17
+ /* Which mode the component is in. When created by dragging, acts in 'create' mode, otherwise is 'normal'. Can be overridden in options. */
15
18
  dragMode: 'create',
19
+
20
+ /* The previous coordinate. Used to detect double-drag as double-click */
16
21
  prevXY: [0,0],
22
+
23
+ /* The time at the previous coordinate. Used to detect double-drag as double-click. */
17
24
  prevXYTime: 0,
18
25
 
26
+ defaultEvents: {
27
+ draggable: true,
28
+ click: true,
29
+ doubleClick: true
30
+ },
31
+
32
+ controlDefaults: HControlDefaults.extend({
33
+ dragMode: 'create',
34
+ constructor: function(_ctrl){
35
+ _ctrl.dragMode = this.dragMode;
36
+ }
37
+ }),
38
+
19
39
  /** = Description
20
40
  * Dragging is used to change coordinates.
21
41
  *
@@ -31,13 +51,8 @@ HTimeSheetItem = HControl.extend({
31
51
  _xEquals = (Math.round(this.prevXY[0]/4) === Math.round(x/4)),
32
52
  _yEquals = (Math.round(this.prevXY[1]/4) === Math.round(y/4)),
33
53
  _noTimeout = ((_timeNow - this.prevXYTime) < 500);
34
- if( _xEquals && _yEquals && _noTimeout ) {
35
- if( this.parent['editor'] ){
36
- var _editor = this.parent.editor;
37
- _editor.setTimeSheetItem(this);
38
- _editor.bringToFront();
39
- _editor.show();
40
- }
54
+ if( _xEquals && _yEquals && _noTimeout ) { // doubleClick
55
+ return true;
41
56
  }
42
57
  else {
43
58
  var _diffTop = this.rect.top - this.origY,
@@ -60,6 +75,17 @@ HTimeSheetItem = HControl.extend({
60
75
  return true;
61
76
  },
62
77
 
78
+ doubleClick: function(x,y){
79
+ if( this.parent['editor'] ){
80
+ var _editor = this.parent.editor;
81
+ _editor.setTimeSheetItem(this);
82
+ _editor.bringToFront();
83
+ _editor.show();
84
+ return true;
85
+ }
86
+ return false;
87
+ },
88
+
63
89
  /** = Description
64
90
  * Label setter function.
65
91
  *
@@ -203,23 +229,27 @@ HTimeSheetItem = HControl.extend({
203
229
  *
204
230
  **/
205
231
  endDrag: function(x,y){
206
- var _pxPerHour = Math.floor(this.parent.pxPerHour),
207
- _value;
232
+ var
233
+ _pxPerHour = Math.floor(this.parent.pxPerHour),
234
+ _value,
235
+ _yEquals = (Math.round(this.prevXY[1]/4) === Math.round(y/4));
236
+ if(_yEquals){ // nothing moved, just return.
237
+ return true;
238
+ }
208
239
  if(this.dragMode === 'create'){
209
240
  this.parent.listItemViews.push( this );
210
- _value = {
211
- 'timeBegin': this.rect.top/_pxPerHour,
212
- 'timeEnd': this.rect.bottom/_pxPerHour,
213
- 'label': this.label
214
- };
241
+ _value = {};
242
+ this._setValueTop( _value );
243
+ this._setValueBottom( _value );
244
+ this._setValueLabel( _value );
215
245
  if(this.parent['editor']){
216
246
  this.parent.editor.createItem( _value );
217
247
  }
218
248
  }
219
249
  else {
220
250
  _value = COMM.Values.clone( this.value );
221
- _value['timeBegin'] = this.rect.top/_pxPerHour;
222
- _value['timeEnd'] = this.rect.bottom/_pxPerHour;
251
+ this._setValueTop( _value );
252
+ this._setValueBottom( _value );
223
253
  if(this.parent['editor']){
224
254
  this.parent.editor.modifyItem( _value );
225
255
  }
@@ -229,17 +259,47 @@ HTimeSheetItem = HControl.extend({
229
259
  return true;
230
260
  },
231
261
 
262
+ _setValueTop: function( _value ) {
263
+ _value['timeBegin'] = this.rect.top/this.parent.pxPerHour;
264
+ },
265
+
266
+ _setValueBottom: function( _value ) {
267
+ _value['timeEnd'] = this.rect.bottom/this.parent.pxPerHour;
268
+ },
269
+
270
+ _setValueLabel: function( _value ) {
271
+ _value['label'] = this.label;
272
+ },
273
+
274
+ _getValueLabel: function( _value ){
275
+ return _value.label;
276
+ },
277
+
278
+ _getValueTop: function( _value ){
279
+ return (_value.timeBegin * this.parent.pxPerHour)+1;
280
+ },
281
+
282
+ _getValueBottom: function( _value ){
283
+ return (_value.timeEnd * this.parent.pxPerHour)-2;
284
+ },
285
+
232
286
  /** = Description
233
287
  * Refreshes the object's label and place on the HTimeSheet.
234
288
  *
235
289
  **/
236
290
  refreshValue: function(){
237
- var _value = this.value,
238
- _pxPerHour = this.parent.pxPerHour;
239
- if((_value instanceof Object) && !(_value instanceof Array)){
240
- this.setLabel( _value['label'] );
241
- this.rect.setTop( _value['timeBegin'] * _pxPerHour );
242
- this.rect.setBottom( _value['timeEnd'] * _pxPerHour );
291
+ if ( HVM.type(this.value) === 'h' ){
292
+ var
293
+ _label = this._getValueLabel( this.value ),
294
+ _top = this._getValueTop( this.value ),
295
+ _bottom = this._getValueBottom( this.value ),
296
+ _minHeight = this.parent.options.itemMinHeight;
297
+ this.setLabel( _label );
298
+ if( (_bottom - _top) < _minHeight ){
299
+ _bottom = _top + _minHeight;
300
+ }
301
+ this.rect.setTop( _top );
302
+ this.rect.setBottom( _bottom );
243
303
  this.drawRect();
244
304
  }
245
305
  }
@@ -187,10 +187,16 @@ HApplication = HClass.extend({
187
187
  * resistant. Do not extend.
188
188
  **/
189
189
  _startIdle: function(){
190
- HSystem.busyApps[ this.appId ] = true;
191
- this.onIdle();
192
- this._pollViews();
193
- HSystem.busyApps[ this.appId ] = false;
190
+ var _this = this;
191
+ HSystem.busyApps[ _this.appId ] = true;
192
+ this._busyTimer = setTimeout(
193
+ function(){
194
+ _this.onIdle();
195
+ _this._pollViews();
196
+ HSystem.busyApps[ _this.appId ] = false;
197
+ },
198
+ 10
199
+ );
194
200
  },
195
201
 
196
202
  /** = Description