rsence-pre 2.1.8.1 → 2.2.0.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 (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