rsence-pre 2.1.8.1 → 2.2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/INSTALL.rdoc +3 -3
  2. data/README.rdoc +4 -4
  3. data/VERSION +1 -1
  4. data/conf/default_conf.yaml +4 -1
  5. data/js/comm/sessionwatcher/sessionwatcher.js +3 -2
  6. data/js/controls/textcontrol/textcontrol.js +45 -19
  7. data/js/core/elem/elem.js +6 -0
  8. data/js/datetime/timesheet/old_timesheet.js +292 -0
  9. data/js/datetime/timesheet/themes/default/old_timesheet.css +30 -0
  10. data/js/datetime/timesheet/themes/default/old_timesheet.html +2 -0
  11. data/js/datetime/timesheet/themes/default/timesheet.css +50 -22
  12. data/js/datetime/timesheet/themes/default/timesheet.html +4 -2
  13. data/js/datetime/timesheet/timesheet.js +448 -159
  14. data/js/datetime/timesheet_item/old_timesheet_item.js +308 -0
  15. data/js/datetime/timesheet_item/themes/default/old_timesheet_item.css +42 -0
  16. data/js/datetime/timesheet_item/themes/default/old_timesheet_item.html +8 -0
  17. data/js/datetime/timesheet_item/themes/default/timesheet_item.css +42 -11
  18. data/js/datetime/timesheet_item/themes/default/timesheet_item.html +4 -2
  19. data/js/datetime/timesheet_item/themes/default/timesheet_item_icons.png +0 -0
  20. data/js/datetime/timesheet_item/timesheet_item.js +156 -259
  21. data/js/datetime/timesheet_item_edit/old_timesheet_item_edit.js +274 -0
  22. data/js/datetime/timesheet_item_edit/timesheet_item_edit.js +0 -274
  23. data/js/foundation/control/valueaction/js.inc +0 -0
  24. data/js/foundation/control/valueaction/valueaction.js +72 -0
  25. data/js/foundation/locale_settings/js.inc +0 -0
  26. data/js/foundation/locale_settings/locale_settings.js +122 -0
  27. data/js/foundation/system/system.js +3 -2
  28. data/js/foundation/view/view.js +27 -0
  29. data/js/lists/checkboxlist/checkboxlist.js +9 -0
  30. data/js/lists/listitems/listitems.js +16 -0
  31. data/js/lists/radiobuttonlist/radiobuttonlist.js +17 -1
  32. data/js/menus/minimenu/minimenu.js +9 -5
  33. data/lib/conf/argv.rb +1 -0
  34. metadata +21 -9
@@ -6,149 +6,367 @@
6
6
  * with this software package. If not, contact licensing@riassence.com
7
7
  */
8
8
 
9
- /*** = Description
10
- ** HTimesheet is a simple timesheet control.
11
- ***/
9
+ HLocale.components.HTimeSheet = {
10
+ strings: {
11
+ newItemLabel: 'New item'
12
+ }
13
+ };
14
+
15
+
12
16
  var//RSence.DateTime
13
17
  HTimeSheet = HControl.extend({
14
18
 
15
- componentName: 'timesheet',
16
-
17
- /* Default amount of pixels per hour. Override with options when necessary. */
18
- pxPerHour: 24,
19
+ debug: false,
19
20
 
20
- /* Default amount of pixels from left. Override with options when necessary. */
21
- itemOffsetLeft: 36,
22
-
23
- /* Default amount of pixels from right. Override with options when necessary. */
24
- itemOffsetRight: 0,
21
+ localeStrings: HLocale.components.HTimeSheet.strings,
22
+ componentName: 'timesheet',
23
+ markupElemNames: [
24
+ 'label', 'value', 'timeline'
25
+ ],
25
26
 
26
27
  defaultEvents: {
27
- draggable: true
28
+ draggable: true,
29
+ click: true,
30
+ doubleClick: true,
31
+ resize: true
28
32
  },
29
33
 
30
34
  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;
35
+ timeStart: 0, // 1970-01-01 00:00:00
36
+ timeEnd: 86399, // 1970-01-01 23:59:59
37
+ tzOffset: 0, // timezone offset in seconds; eg: 7200 => UTC+2
38
+ itemMinHeight: 16,
39
+ hideHours: false,
40
+ autoLabel: false, // automatically set the label to the date
41
+ autoLabelFn: 'formatDate',
42
+ autoLabelFnOptions: { longWeekDay: true },
43
+ notchesPerHour: 4, // by default 1/4 of an hour precision (15 minutes)
44
+ itemOffsetLeft: 64, // Theme settings; don't enter in options
45
+ itemOffsetRight: 0, // Theme settings; don't enter in options
46
+ itemOffsetTop: 20, // Theme settings; don't enter in options
47
+ itemOffsetBottom: 0, // Theme settings; don't enter in options
48
+ hourOffsetTop: -4, // Theme settings; don't enter in options
49
+ constructor: function( _ctrl ){
50
+ if( this.defaultLabel === undefined ){
51
+ this.defaultLabel = _ctrl.localeStrings.newItemLabel;
39
52
  }
40
- if(this.itemOffsetLeft !== null){
41
- _ctrl.itemOffsetLeft = this.itemOffsetLeft;
53
+ }
54
+ }),
55
+
56
+ themeSettings: function( _itemOffsetLeft, _itemOffsetTop, _itemOffsetRight, _itemOffsetBottom, _hourOffsetTop ){
57
+ if( this.options.hideHours ){
58
+ ELEM.addClassName( this.elemId, 'nohours' );
59
+ this.options.itemOffsetLeft = 0;
60
+ }
61
+ else if( _itemOffsetLeft !== undefined ) {
62
+ this.options.itemOffsetLeft = _itemOffsetLeft;
63
+ }
64
+ if( _itemOffsetTop !== undefined ) {
65
+ this.options.itemOffsetTop = _itemOffsetTop;
66
+ }
67
+ if( _itemOffsetRight !== undefined ) {
68
+ this.options.itemOffsetRight = _itemOffsetRight;
69
+ }
70
+ if( _itemOffsetBottom !== undefined ) {
71
+ this.options.itemOffsetBottom = _itemOffsetBottom;
72
+ }
73
+ if( _hourOffsetTop !== undefined ) {
74
+ this.options.hourOffsetTop = _hourOffsetTop;
75
+ }
76
+ },
77
+
78
+ autoLabel: function(){
79
+ var
80
+ _locale = HLocale.dateTime,
81
+ _label = _locale[this.options.autoLabelFn]( this.options.timeStart, this.options.autoLabelFnOptions );
82
+ if( this.label !== _label ){
83
+ this.label = _label;
84
+ this.refreshLabel();
85
+ }
86
+ },
87
+
88
+ clearHours: function(){
89
+ for( var i = 0; i < this.hourItems.length; i++ ){
90
+ ELEM.del( this.hourItems[i] );
91
+ }
92
+ },
93
+
94
+ drawHours: function(){
95
+
96
+ var
97
+ _parentElemId = this.markupElemIds.timeline,
98
+ _dateStart = new Date( this.options.timeStart * 1000 ),
99
+ _dateEnd = new Date( this.options.timeEnd * 1000 ),
100
+ _hourStart = _dateStart.getUTCHours(),
101
+ _hourEnd = _dateEnd.getUTCHours(),
102
+ _hours = (_hourEnd - _hourStart) + 1,
103
+ _rectHeight = ELEM.getSize( _parentElemId )[1],
104
+ _topOffset = this.options.itemOffsetTop,
105
+ _height = _rectHeight - _topOffset - this.options.itemOffsetBottom,
106
+ _pxPerHour = _height / _hours,
107
+ _notchesPerHour = this.options.notchesPerHour,
108
+ _pxPerLine = _pxPerHour / _notchesPerHour,
109
+ _hour = _hourStart,
110
+ _bottomPos = _rectHeight-_height-_topOffset-2,
111
+ _hourItem,
112
+ _lineItem,
113
+ _hourTop,
114
+ _lineTop,
115
+ i,
116
+ _pxPerNotch = _pxPerHour / _notchesPerHour,
117
+ _notchItem,
118
+ _notchTop;
119
+
120
+ ELEM.setStyle( _parentElemId, 'visibility', 'hidden', true );
121
+
122
+ ELEM.setStyle( this.markupElemIds.value, 'bottom', _bottomPos+'px' );
123
+
124
+ if( this['hourItems'] !== undefined ){
125
+ this.clearHours();
126
+ }
127
+ this.itemOptions = {
128
+ notchHeight: _pxPerNotch,
129
+ notches: (_hours * _notchesPerHour),
130
+ offsetTop: _topOffset,
131
+ offsetBottom: _bottomPos,
132
+ height: _height
133
+ };
134
+ this.hourItems = [];
135
+ for( ; _hour < (_hourEnd+1); _hour++ ){
136
+ _hourItem = ELEM.make( this.markupElemIds.timeline, 'div' );
137
+ _lineTop = Math.round(_topOffset + (_hour*_pxPerHour));
138
+ if( _hour !== _hourStart ){
139
+ _hourTop = _lineTop + this.options.hourOffsetTop;
140
+ ELEM.setStyle( _hourItem, 'top', _hourTop+'px' );
141
+ ELEM.addClassName( _hourItem, 'timesheet_timeline_hour' );
142
+ ELEM.setHTML( _hourItem, _hour+':00' );
143
+ this.hourItems.push( _hourItem );
144
+ _lineItem = ELEM.make( _parentElemId, 'div' );
145
+ ELEM.addClassName( _lineItem, 'timesheet_timeline_line' );
146
+ ELEM.setStyle( _lineItem, 'top', _lineTop + 'px' );
147
+ this.hourItems.push( _lineItem );
42
148
  }
43
- if(this.itemOffsetRight !== null){
44
- _ctrl.itemOffsetRight = this.itemOffsetRight;
149
+ for( i=1; i < _notchesPerHour; i++ ){
150
+ _notchItem = ELEM.make( _parentElemId, 'div' );
151
+ ELEM.addClassName( _notchItem, 'timesheet_timeline_notch' );
152
+ _notchTop = Math.round(_lineTop + (_pxPerNotch*i));
153
+ ELEM.setStyle( _notchItem, 'top', _notchTop+'px' );
154
+ this.hourItems.push( _notchItem );
45
155
  }
46
156
  }
47
- }),
157
+
158
+ ELEM.setStyle( this.markupElemIds.timeline, 'visibility', 'inherit' );
159
+
160
+ },
48
161
 
49
- /** = Description
50
- * Redraws the timesheet.
51
- *
52
- **/
53
162
  refresh: function(){
54
- if(this.drawn){
55
- var _areaHeight = this.rect.height;
56
- this.pxPerHour = (_areaHeight-(_areaHeight%48)) / 24;
57
- if(this.options['hideLabel']){
58
- this.setStyleOfPart( 'label', 'display', 'none' );
59
- this.setStyleOfPart( 'state', 'left', '0px' );
60
- this.itemOffsetLeft = 0;
61
- }
62
- else{
63
- this.setStyleOfPart( 'label', 'height', (this.pxPerHour*24)+'px' );
163
+ if( this.drawn ){
164
+ if( this.options.autoLabel ){
165
+ this.autoLabel();
64
166
  }
65
- this.setStyleOfPart( 'state', 'height', (this.pxPerHour*24)+'px' );
167
+ this.drawHours();
66
168
  }
67
169
  this.base();
68
170
  },
69
171
 
70
- /** = Description
71
- * Refreshes the hour labels.
72
- *
73
- **/
74
- refreshLabel: function(){
75
- var hour = 1,
76
- hours = [],
77
- rowHeight = this.pxPerHour;
78
- lineHeight = Math.round(this.pxPerHour/2);
79
- for(; hour < 24; hour++){
80
- hours.push('<div style="line-height:'+rowHeight+'px;height:'+rowHeight+'px;top:'+Math.round((hour*rowHeight)-lineHeight)+'px" class="timesheet_hours_row">'+hour+':00</div>');
81
- }
82
- this.markupElemIds && this.markupElemIds.label && ELEM.setHTML(this.markupElemIds.label,hours.join(''));
83
- this.refreshState();
172
+ setTzOffset: function( _tzOffset ){
173
+ this.options.tzOffset = _tzOffset;
174
+ this.refresh();
84
175
  },
85
176
 
86
- /** = Description
87
- * Refreshes the lines which mark hours and half-hours.
88
- *
89
- **/
90
- refreshState: function(){
91
- var line = 0,
92
- lines = [],
93
- lineHeight = Math.round(this.pxPerHour/2);
94
- for(; line < 48; line++){
95
- lines.push('<div style="top:'+(line*lineHeight)+'px" class="timesheet_lines_row'+(line%2)+'"></div>');
96
- }
97
- this.markupElemIds && this.markupElemIds.label && ELEM.setHTML(this.markupElemIds.state,lines.join(''));
177
+ setTimeStart: function( _timeStart ){
178
+ this.options.timeStart = _timeStart;
179
+ this.refresh();
98
180
  },
99
- dragItem: false,
100
181
 
101
- /** = Description
102
- * Creates an item into timesheet with default label 'New Item'.
103
- *
104
- * = Parameters
105
- * +origY+:: Y coordinate of the new item.
106
- *
107
- **/
108
- createItem: function(origY){
109
- var _lineHeight = Math.round(this.pxPerHour/2);
110
- origY = Math.floor( origY / _lineHeight )*_lineHeight;
111
- var maxY = _lineHeight*48,
112
- lineHeight = Math.round(this.pxPerHour/2);
113
- if(origY>maxY){
114
- origY = maxY;
115
- }
116
- this.dragItem = this.createTimeSheetItem( { label: this.options.newItemLabel }, origY, lineHeight, 'create' );
182
+ setTimeEnd: function( _timeEnd ){
183
+ this.options.timeEnd = _timeEnd;
184
+ this.refresh();
117
185
  },
118
186
 
119
- /** = Description
120
- * Dragging is used to mark items on the timesheet.
121
- *
122
- * = Parameters
123
- * +x+:: x coordinate of the origin of drag
124
- * +y+:: y coordinate of the origin of drag
125
- *
126
- **/
127
- startDrag: function(x,y){
128
- this._startDragTime = new Date().getTime();
129
- this._startDragCoords = [x,y];
130
- return true;
187
+ setTimeRange: function( _timeRange ){
188
+ if( (_timeRange instanceof Array) && (_timeRange.length === 2) ){
189
+ this.setTimeStart( _timeRange[0] );
190
+ this.setTimeEnd( _timeRange[1] );
191
+ }
192
+ else if(
193
+ (_timeRange instanceof Object) &&
194
+ (_timeRange['timeStart'] !== undefined) &&
195
+ (_timeRange['timeEnd'] !== undefined)
196
+ ){
197
+ this.setTimeStart( _timeRange.timeStart );
198
+ this.setTimeEnd( _timeRange.timeEnd );
199
+ }
131
200
  },
132
201
 
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;
202
+ setDate: function( _date ){
203
+ var
204
+ _range = (this.options.timeEnd - this.options.timeStart),
205
+ _newTimeRange = [
206
+ _date,
207
+ _date + _range
208
+ ];
209
+ this.setTimeRange( _newTimeRange );
210
+ this.refresh();
211
+ },
212
+
213
+ drawSubviews: function(){
214
+ this.drawHours();
215
+ var
216
+ _options = this.options,
217
+ _minDuration = Math.round(3600/_options.notchesPerHour),
218
+ _dummyValue = {
219
+ // id: 'new',
220
+ label: '',
221
+ start: 0,
222
+ duration: _minDuration,
223
+ // locked: false,
224
+ color: '#c00'
225
+ };
226
+ this.dragPreviewRect = this.rectFromValue({start:_options.timeStart,duration:_minDuration});
227
+ this.minDuration = _minDuration;
228
+ this.dragPreview = HTimeSheetItem.nu(
229
+ this.dragPreviewRect,
230
+ this, {
231
+ value: _dummyValue,
232
+ visible: false
233
+ }
234
+ );
235
+ this.dragPreview.setStyleOfPart('state','color','#fff');
236
+ },
237
+
238
+ click: function( x, y, b ){
239
+ // console.log('click');
240
+ if( !this.startDragTime ){
241
+ this.clickCreate( x,y );
242
+ this.clickCreated = true;
137
243
  }
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;
244
+ this.clickCreated = false;
245
+ },
246
+
247
+ clickCreate: function(x,y){
248
+ // console.log('clickCreate');
249
+ y -= this.pageY();
250
+ var
251
+ _startTime = this.pxToTime( y ),
252
+ _endTime = _startTime + this.minDuration;
253
+ this.refreshDragPreview( _startTime, _endTime );
254
+ this.dragPreview.bringToFront();
255
+ this.dragPreview.show();
256
+ if( this.activateEditor( this.dragPreview ) ){
257
+ // console.log('create!');
258
+ this.editor.createItem( HVM.clone( this.dragPreview.value ) );
259
+ }
260
+ else {
261
+ // console.log('no create');
262
+ this.dragPreview.hide();
142
263
  }
143
264
  },
144
265
 
145
- click: function(x,y){
146
- // deactivate all items
147
- EVENT.changeActiveControl(this);
266
+ doubleClick: function(x,y){
267
+ // console.log('doubleClick');
268
+ if( !this.clickCreated ){
269
+ this.click(x,y);
270
+ }
271
+ this.clickCreated = false;
272
+ },
273
+
274
+ refreshDragPreview: function( _startTime, _endTime ){
275
+ this.dragPreviewRect.setTop( this.timeToPx( _startTime, true ) );
276
+ this.dragPreviewRect.setBottom( this.timeToPx( _endTime, true ) );
277
+ if( this.dragPreviewRect.height < this.options.itemMinHeight ){
278
+ this.dragPreviewRect.setHeight( this.options.itemMinHeight );
279
+ }
280
+ this.dragPreview.drawRect();
281
+ this.dragPreview.value.start = _startTime;
282
+ this.dragPreview.value.duration = _endTime - _startTime;
283
+ this.dragPreview.refreshValue();
284
+ },
285
+
286
+ startDrag: function( x, y, b ){
287
+ y -= this.pageY();
288
+ this.startDragTime = this.pxToTime( y );
289
+ this.refreshDragPreview( this.startDragTime, this.startDragTime + this.minDuration );
290
+ this.dragPreview.bringToFront();
291
+ this.dragPreview.show();
148
292
  return true;
149
293
  },
150
294
 
151
- listItemViews: false,
295
+ drag: function( x, y, b ){
296
+ y -= this.pageY();
297
+ var
298
+ _dragTime = this.pxToTime( y ),
299
+ _startTime,
300
+ _endTime;
301
+ if( _dragTime < this.startDragTime ){
302
+ _startTime = _dragTime;
303
+ _endTime = this.startDragTime;
304
+ }
305
+ else {
306
+ _endTime = _dragTime;
307
+ _startTime = this.startDragTime;
308
+ }
309
+ this.refreshDragPreview( _startTime, _endTime );
310
+ return true;
311
+ },
312
+
313
+ endDrag: function( x, y, b ){
314
+ y -= this.pageY();
315
+ var _dragTime = this.pxToTime( y );
316
+ if( _dragTime !== this.startDragTime ){
317
+ if( this.activateEditor( this.dragPreview ) ){
318
+ this.editor.createItem( HVM.clone( this.dragPreview.value ) );
319
+ return true;
320
+ }
321
+ }
322
+ this.clickCreated = false;
323
+ this.dragPreview.hide();
324
+ this.startDragTime = false;
325
+ return false;
326
+ },
327
+
328
+ resize: function(){
329
+ this.base();
330
+ this.refresh();
331
+ },
332
+ debugPos: function( _px, color ){
333
+ var _debugPosId = ELEM.make(this.elemId,'div');
334
+ ELEM.setCSS(_debugPosId,'position:absolute;left:0px;top:'+_px+'px;right:0px;background-color:'+color+';height:1px;');
335
+ setTimeout( function(){ ELEM.del( _debugPosId ); }, 1000 );
336
+ },
337
+ snapTime: function( _timeSecs ){
338
+ var
339
+ _options = this.options,
340
+ _pxDate = new Date( Math.round(_timeSecs) * 1000 ),
341
+ _snapSecs = Math.round( 3600 / _options.notchesPerHour ),
342
+ _halfSnapSecs = _snapSecs * 0.5,
343
+ _hourSecs = (_pxDate.getUTCMinutes()*60) + _pxDate.getUTCSeconds(),
344
+ _remSecs = _hourSecs % _snapSecs;
345
+ if( _remSecs > _halfSnapSecs ){
346
+ _timeSecs += _snapSecs-_remSecs;
347
+ }
348
+ else {
349
+ _timeSecs -= _remSecs;
350
+ }
351
+ return _timeSecs;
352
+ },
353
+ snapPx: function( _px ){
354
+ var
355
+ _timeSecs = this.pxToTime( _px );
356
+ _timeSecs = this.snapTime( _timeSecs );
357
+ return this.timeToPx( _timeSecs );
358
+ },
359
+ activateEditor: function( _item ){
360
+ if( this['editor'] ){
361
+ var _editor = this.editor;
362
+ _editor.setTimeSheetItem( _item );
363
+ _item.bringToFront();
364
+ _editor.bringToFront();
365
+ _editor.show();
366
+ return true;
367
+ }
368
+ return false;
369
+ },
152
370
 
153
371
  /** = Description
154
372
  * Sets the editor given as parameter as the editor of instance.
@@ -160,82 +378,150 @@ HTimeSheet = HControl.extend({
160
378
  setEditor: function( _editor ){
161
379
  this.editor = _editor;
162
380
  },
163
-
164
- /** = Description
165
- * Returns HRect the size of given parameters and suitable for timesheet.
166
- *
167
- * = Parameters
168
- * +_origY+:: Y coordinate.
169
- * +_lineHeight+:: The height of item on time sheet.
170
- *
171
- **/
172
- createItemRect: function(_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
- }
180
- return HRect.nu( _left, _top, _right, _bottom );
181
- },
182
-
183
381
  /** = Description
184
382
  * Destructor; destroys the editor first and commences inherited die.
185
383
  *
186
384
  **/
187
385
  die: function(){
188
- this.editor.die();
386
+ this.editor && this.editor.die();
387
+ this.editor = null;
189
388
  this.base();
190
389
  },
191
390
 
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';
391
+ pxToTime: function( _px, _noSnap ){
392
+ var
393
+ _options = this.options,
394
+ _timeStart = _options.timeStart,
395
+ _timeEnd = _options.timeEnd,
396
+ _timeRange = _timeEnd - _timeStart,
397
+ _itemOptions = this.itemOptions,
398
+ _top = _itemOptions.offsetTop+1,
399
+ _height = _itemOptions.height,
400
+ _pxPerSec = _height / _timeRange,
401
+ _timeSecs;
402
+ _px -= _top;
403
+ _timeSecs = _timeStart + ( _px / _pxPerSec );
404
+ if( !_noSnap ){
405
+ _timeSecs = this.snapTime( _timeSecs );
406
+ }
407
+ if( _timeSecs > _options.timeEnd ){
408
+ _timeSecs = _options.timeEnd;
409
+ }
410
+ else if ( _timeSecs < _options.timeStart ) {
411
+ _timeSecs = _options.timeStart;
412
+ }
413
+ return Math.round( _timeSecs );
414
+ },
415
+ timeToPx: function( _time, _snap ){
416
+
417
+ if( _snap ){
418
+ _time = this.snapTime( _time );
419
+ }
420
+
421
+ var
422
+ _options = this.options,
423
+ _timeStart = _options.timeStart,
424
+ _timeEnd = _options.timeEnd;
425
+
426
+ if( _time < _timeStart ){
427
+ _time = _timeStart;
428
+ // this.debug && console.log('time:',_time,' is less than timeStart:',_timeStart);
429
+ // return 'underflow';
430
+ }
431
+ if( _time > _timeEnd ){
432
+ _time = _timeEnd;
433
+ // this.debug && console.log('time:',_time,' is more than timeEnd:',_timeEnd);
434
+ // return 'overflow';
207
435
  }
208
- if(_top===undefined){
209
- _top = 0;
436
+
437
+ var
438
+ _timeRange = _timeEnd - _timeStart,
439
+ _itemOptions = this.itemOptions,
440
+ _top = _itemOptions.offsetTop,
441
+ _height = _itemOptions.height,
442
+ _pxPerSec = _height / _timeRange,
443
+ _timeSecs = _time - _timeStart,
444
+ _px = _top + ( _timeSecs * _pxPerSec );
445
+ return Math.round( _px );
446
+ },
447
+ rectFromValue: function( _value ){
448
+ var
449
+ _topPx = this.timeToPx( _value.start ),
450
+ _bottomPx = this.timeToPx( _value.start + _value.duration ),
451
+ _leftPx = this.options.itemOffsetLeft,
452
+ _rightPx = this.rect.width - this.options.itemOffsetRight - 2,
453
+ _rect;
454
+ if( _topPx === 'underflow' ){
455
+ _topPx = _itemOptions.offsetTop;
456
+ }
457
+ else if( _topPx === 'overflow' ){
458
+ this.debug && console.log('item out of range:',_value);
459
+ return false;
210
460
  }
211
- if(_height===undefined){
212
- _height = Math.round(this.pxPerHour/2);
461
+ if( _bottomPx === 'underflow' ){
462
+ this.debug && console.log('item out of range:',_value);
463
+ return false;
213
464
  }
465
+ else if( _bottomPx === 'overflow' ){
466
+ _bottomPx = _itemOptions.offsetTop + _itemOptions.height;
467
+ }
468
+ _rect = HRect.nu( _leftPx, _topPx, _rightPx, _bottomPx );
469
+ if( _rect.height < this.options.itemMinHeight ){
470
+ _rect.setHeight( this.options.itemMinHeight );
471
+ }
472
+ return _rect;
473
+ },
474
+ createTimeSheetItem: function( _value ){
214
475
  var
215
- _label = _value['label'],
476
+ _rect = this.rectFromValue( _value ),
477
+ _item;
478
+ if( _rect === false ){
479
+ this.debug && console.log('invalid item:',_value);
480
+ return false;
481
+ }
216
482
  _item = HTimeSheetItem.nu(
217
- this.createItemRect( _top, _height ),
483
+ _rect,
218
484
  this, {
219
- label: _label,
220
485
  value: _value,
221
486
  events: {
222
- draggable: true
487
+ draggable: true,
488
+ // click: true,
489
+ doubleClick: true
223
490
  }
224
491
  }
225
492
  );
226
- _item.dragMode = _dragMode;
227
493
  return _item;
228
494
  },
229
-
495
+ /*
496
+
497
+ Each item looks like this, any extra attributes are allowed,
498
+ but not used and not guaranteed to be preserved:
499
+
500
+ {
501
+ id: 'abcdef1234567890', // identifier, used in server to map id's
502
+ label: 'Event title', // label of event title
503
+ start: 1299248619, // epoch timestamp of event start
504
+ duration: 3600, // duration of event in seconds
505
+ locked: true, // when false, prevents editing the item
506
+ icons: [ 1, 3, 6 ], // icon id's to display
507
+ color: '#ffffff' // defaults to '#ffffff' if undefined
508
+ }
509
+
510
+
511
+ */
230
512
  /** = Description
231
513
  * Redraws and refreshes the values on timesheet.
232
514
  *
233
515
  **/
234
516
  refreshValue: function(){
517
+ if(!this.itemOptions){
518
+ return;
519
+ }
520
+ this.dragPreview.hide();
235
521
  var
236
522
  _data = this.value,
237
523
  i;
238
- if(this.listItemViews === false){
524
+ if(this.listItemViews === undefined){
239
525
  this.listItemViews = [];
240
526
  }
241
527
  else if(this.listItemViews.length > 0){
@@ -244,14 +530,16 @@ HTimeSheet = HControl.extend({
244
530
  }
245
531
  this.listItemViews = [];
246
532
  }
247
- if(_data instanceof Array && _data.length > 0){
533
+ if((_data instanceof Array) && (_data.length > 0)){
248
534
  var
249
535
  _value,
250
536
  _item;
251
537
  for( i=0; i<_data.length; i++){
252
538
  _value = _data[i];
253
539
  _item = this.createTimeSheetItem( _value );
254
- this.listItemViews.push( _item );
540
+ if(_item){
541
+ this.listItemViews.push( _item );
542
+ }
255
543
  }
256
544
  }
257
545
  var
@@ -269,9 +557,9 @@ HTimeSheet = HControl.extend({
269
557
  var
270
558
  _overlapCount = _overlaps.length+1,
271
559
  _overlapLefts = {},
272
- _itemWidth = ( this.rect.width - this.itemOffsetRight - this.itemOffsetLeft ),
560
+ _itemWidth = ( this.rect.width - this.options.itemOffsetRight - this.options.itemOffsetLeft ),
273
561
  _width = Math.floor( _itemWidth / _overlapCount),
274
- _left = this.itemOffsetLeft;
562
+ _left = this.options.itemOffsetLeft;
275
563
  for(j=0;j<_overlapCount;j++){
276
564
  _overlapLefts[_overlaps[j]] = _left + (j*_width) + _width;
277
565
  }
@@ -288,5 +576,6 @@ HTimeSheet = HControl.extend({
288
576
  this.listItemViews[i].drawRect();
289
577
  }
290
578
  }
579
+
291
580
  });
292
581