rsence 2.1.10 → 2.1.11

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.
@@ -48,7 +48,7 @@ Event = {
48
48
  **/
49
49
  isLeftClick: function(e) {
50
50
  // IE: left 1, middle 4, right 2
51
- if (BROWSER_TYPE.ie) {
51
+ if (BROWSER_TYPE.ie && !BROWSER_TYPE.ie9) {
52
52
  return (e.button === 1 || e.button === 3 || e.button === 5);
53
53
  }
54
54
  else {
@@ -147,7 +147,7 @@ Event = {
147
147
 
148
148
  // Activates the garbage collector of Internet Explorer
149
149
  // when the document is unloaded:
150
- if (BROWSER_TYPE.ie) {
150
+ if (BROWSER_TYPE.ie && !BROWSER_TYPE.ie9) {
151
151
  Event.observe(window, "unload", Event.unloadCache, false);
152
152
  }
153
153
 
@@ -0,0 +1,292 @@
1
+ /* RSence
2
+ * Copyright 2009 Riassence Inc.
3
+ * http://riassence.com/
4
+ *
5
+ * You should have received a copy of the GNU General Public License along
6
+ * with this software package. If not, contact licensing@riassence.com
7
+ */
8
+
9
+ /*** = Description
10
+ ** HTimesheet is a simple timesheet control.
11
+ ***/
12
+ var//RSence.DateTime
13
+ HTimeSheet = HControl.extend({
14
+
15
+ componentName: 'timesheet',
16
+
17
+ /* Default amount of pixels per hour. Override with options when necessary. */
18
+ pxPerHour: 24,
19
+
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,
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
+
49
+ /** = Description
50
+ * Redraws the timesheet.
51
+ *
52
+ **/
53
+ 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' );
64
+ }
65
+ this.setStyleOfPart( 'state', 'height', (this.pxPerHour*24)+'px' );
66
+ }
67
+ this.base();
68
+ },
69
+
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();
84
+ },
85
+
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(''));
98
+ },
99
+ dragItem: false,
100
+
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' );
117
+ },
118
+
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;
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
+
151
+ listItemViews: false,
152
+
153
+ /** = Description
154
+ * Sets the editor given as parameter as the editor of instance.
155
+ *
156
+ * = Parameters
157
+ * +_editor+::
158
+ *
159
+ **/
160
+ setEditor: function( _editor ){
161
+ this.editor = _editor;
162
+ },
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
+ /** = Description
184
+ * Destructor; destroys the editor first and commences inherited die.
185
+ *
186
+ **/
187
+ die: function(){
188
+ this.editor.die();
189
+ this.base();
190
+ },
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
+
230
+ /** = Description
231
+ * Redraws and refreshes the values on timesheet.
232
+ *
233
+ **/
234
+ refreshValue: function(){
235
+ var
236
+ _data = this.value,
237
+ i;
238
+ if(this.listItemViews === false){
239
+ this.listItemViews = [];
240
+ }
241
+ else if(this.listItemViews.length > 0){
242
+ for( i=0; i<this.listItemViews.length; i++){
243
+ this.listItemViews[i].die();
244
+ }
245
+ this.listItemViews = [];
246
+ }
247
+ if(_data instanceof Array && _data.length > 0){
248
+ var
249
+ _value,
250
+ _item;
251
+ for( i=0; i<_data.length; i++){
252
+ _value = _data[i];
253
+ _item = this.createTimeSheetItem( _value );
254
+ this.listItemViews.push( _item );
255
+ }
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
+ }
290
+ }
291
+ });
292
+
@@ -0,0 +1,30 @@
1
+ .timesheet_hours_col {
2
+ position: absolute;
3
+ top: 0px; left: 0px; width: 32px;
4
+ font-family: Arial, sans-serif;
5
+ font-size: 11px;
6
+ color: #666;
7
+ vertical-align: middle;
8
+ text-align: right;
9
+ }
10
+ .timesheet_hours_row {
11
+ position: absolute;
12
+ left: 0px; width: 32px;
13
+ }
14
+ .timesheet_lines_col {
15
+ position: absolute;
16
+ top: 0px; left: 36px; right: 0px;
17
+ border-left: 1px solid #aaa;
18
+ border-bottom: 1px solid #aaa;
19
+ border-right: 1px solid #aaa;
20
+ }
21
+ .timesheet_lines_row0,
22
+ .timesheet_lines_row1 {
23
+ position: absolute;
24
+ left: 0px; right: 0px; height: 1px;
25
+ line-height: 1px; font-size: 0px;
26
+ background-color: #ccc;
27
+ }
28
+ .timesheet_lines_row0 {
29
+ background-color: #aaa;
30
+ }
@@ -0,0 +1,2 @@
1
+ <div class="timesheet_hours_col" id="label#{_ID}"></div>
2
+ <div class="timesheet_lines_col" id="state#{_ID}"></div>
@@ -0,0 +1,308 @@
1
+ /* RSence
2
+ * Copyright 2009 Riassence Inc.
3
+ * http://riassence.com/
4
+ *
5
+ * You should have received a copy of the GNU General Public License along
6
+ * with this software package. If not, contact licensing@riassence.com
7
+ */
8
+
9
+ /*** = Description
10
+ ** Item class to be used with HTimeSheet.
11
+ ***/
12
+ var//RSence.DateTime
13
+ HTimeSheetItem = HControl.extend({
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. */
18
+ dragMode: 'create',
19
+
20
+ /* The previous coordinate. Used to detect double-drag as double-click */
21
+ prevXY: [0,0],
22
+
23
+ /* The time at the previous coordinate. Used to detect double-drag as double-click. */
24
+ prevXYTime: 0,
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
+
39
+ /** = Description
40
+ * Dragging is used to change coordinates.
41
+ *
42
+ * = Parameters
43
+ * +x+:: X coordinate at the start of drag.
44
+ * +y+:: Y coordinate at the start of drag.
45
+ *
46
+ **/
47
+ startDrag: function(x,y){
48
+ this.origY = y-this.parent.pageY();
49
+ if(this.dragMode === 'normal'){
50
+ var _timeNow = new Date().getTime(),
51
+ _xEquals = (Math.round(this.prevXY[0]/4) === Math.round(x/4)),
52
+ _yEquals = (Math.round(this.prevXY[1]/4) === Math.round(y/4)),
53
+ _noTimeout = ((_timeNow - this.prevXYTime) < 500);
54
+ if( _xEquals && _yEquals && _noTimeout ) { // doubleClick
55
+ return true;
56
+ }
57
+ else {
58
+ var _diffTop = this.rect.top - this.origY,
59
+ _diffBottom = this.rect.bottom - this.origY;
60
+ if(0 >= _diffTop && _diffTop >= -3){
61
+ this.dragMode = 'resize-top';
62
+ }
63
+ else if(0 <= _diffBottom && _diffBottom <= 4){
64
+ this.dragMode = 'resize-bottom';
65
+ }
66
+ else {
67
+ this.dragMode = 'move';
68
+ this.moveDiff = this.origY - this.rect.top;
69
+ }
70
+ this.bringToFront();
71
+ }
72
+ }
73
+ this.prevXY = [x,y];
74
+ this.prevXYTime = _timeNow;
75
+ return true;
76
+ },
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
+
89
+ /** = Description
90
+ * Label setter function.
91
+ *
92
+ * = Parameters
93
+ * +_label+:: New label
94
+ *
95
+ **/
96
+ setTimeSheetItemLabel: function(_label){
97
+ this.label = _label;
98
+ this.refreshLabel();
99
+ },
100
+
101
+ /** = Description
102
+ * Function used to calculate the right size for a new
103
+ * item created by dragging.
104
+ *
105
+ * = Parameters
106
+ * +_y+:: Y coordinate at the start of drag.
107
+ *
108
+ **/
109
+ dragCreate: function(_y){
110
+ var _negative = (_y < this.origY),
111
+ _lineHeight = Math.floor(this.parent.pxPerHour/2),
112
+ _top, _bottom, _diff;
113
+ if(_negative){
114
+ var _floorY = Math.floor(_y/_lineHeight)*_lineHeight,
115
+ _ceilYo = Math.ceil(this.origY/_lineHeight)*_lineHeight;
116
+ if(_floorY<0){_floorY=0;}
117
+ _diff = _floorY-_ceilYo;
118
+ if( _diff <= 0-_lineHeight ){
119
+ _top = _floorY;
120
+ _bottom = _ceilYo;
121
+ }
122
+ else if( _diff === 0 ){
123
+ _top = _floorY-_lineHeight;
124
+ _bottom = _ceilYo;
125
+ }
126
+ }
127
+ else {
128
+ var _ceilY = Math.ceil(_y/_lineHeight)*_lineHeight,
129
+ _floorYo = Math.floor(this.origY/_lineHeight)*_lineHeight;
130
+ if(_ceilY>(_lineHeight*48)){_ceilY=_lineHeight*48;}
131
+ _diff = _ceilY-_floorYo;
132
+ if( _diff >= _lineHeight ){
133
+ _top = _floorYo;
134
+ _bottom = _ceilY;
135
+ }
136
+ else if( _diff === 0 ){
137
+ _top = _floorYo;
138
+ _bottom = _ceilY+_lineHeight;
139
+ }
140
+ }
141
+ this.rect.setTop(_top);
142
+ this.rect.setBottom(_bottom);
143
+ },
144
+
145
+ /** = Description
146
+ * Resize top by dragging auxiliary function.
147
+ *
148
+ * = Parameters
149
+ * +_y+:: Y coordinate at the start of drag.
150
+ **/
151
+ dragResizeTop: function(_y){
152
+ var _lineHeight = Math.floor(this.parent.pxPerHour/2),
153
+ _top = Math.floor( _y/_lineHeight )*_lineHeight;
154
+ if(_top < 0){ _top = 0; }
155
+ if(_top+_lineHeight > this.rect.bottom){
156
+ _top = this.rect.bottom - _lineHeight;
157
+ }
158
+ this.rect.setTop( _top );
159
+ },
160
+
161
+ /** = Description
162
+ * Resize function for resizing the bottom of item.
163
+ *
164
+ * = Parameters
165
+ * +_y+:: Y coordinate at the start of drag.
166
+ *
167
+ **/
168
+ dragResizeBottom: function(_y){
169
+ var _lineHeight = Math.floor(this.parent.pxPerHour/2),
170
+ _bottom = Math.floor( _y/_lineHeight )*_lineHeight;
171
+ if(_bottom > _lineHeight*48){ _bottom = _lineHeight*48; }
172
+ if(_bottom-_lineHeight < this.rect.top){
173
+ _bottom = this.rect.top + _lineHeight;
174
+ }
175
+ this.rect.setBottom( _bottom );
176
+ },
177
+
178
+ /** = Description
179
+ * Move function for item by dragging and dropping.
180
+ *
181
+ * = Parameters
182
+ * +_y+:: Y coordinate at the start of drag.
183
+ *
184
+ **/
185
+ dragMove: function(_y){
186
+ var _lineHeight = Math.floor(this.parent.pxPerHour/2),
187
+ _top = Math.floor( (0-this.moveDiff+_y)/_lineHeight )*_lineHeight;
188
+ if(_top<0){_top = 0;}
189
+ if(_top+this.rect.height>_lineHeight*48){
190
+ _top = _lineHeight*48 - this.rect.height;
191
+ }
192
+ this.rect.offsetTo( this.rect.left, _top );
193
+ },
194
+
195
+ /** = Description
196
+ * Drag function for item. Decides whether the user wants to create a new
197
+ * item, resize top, resize bottom or move an existing item.
198
+ *
199
+ * = Parameters
200
+ * +x+:: X coordinate at the start of drag.
201
+ * +y+:: Y coordinate at the start of drag.
202
+ *
203
+ **/
204
+ drag: function(x,y){
205
+ var _pageY = this.parent.pageY(),
206
+ _y = y - _pageY;
207
+ if(this.dragMode === 'create'){
208
+ this.dragCreate(_y);
209
+ }
210
+ else if(this.dragMode === 'resize-top'){
211
+ this.dragResizeTop(_y);
212
+ }
213
+ else if(this.dragMode === 'resize-bottom'){
214
+ this.dragResizeBottom(_y);
215
+ }
216
+ else if(this.dragMode === 'move'){
217
+ this.dragMove(_y);
218
+ }
219
+ this.drawRect();
220
+ return true;
221
+ },
222
+
223
+ /** = Description
224
+ * Modifies the existing item's coordinates or creates a new one.
225
+ *
226
+ * = Parameters
227
+ * +x+:: X coordinate at the end of drag.
228
+ * +y+:: Y coordinate at the end of drag.
229
+ *
230
+ **/
231
+ endDrag: function(x,y){
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
+ }
239
+ if(this.dragMode === 'create'){
240
+ this.parent.listItemViews.push( this );
241
+ _value = {};
242
+ this._setValueTop( _value );
243
+ this._setValueBottom( _value );
244
+ this._setValueLabel( _value );
245
+ if(this.parent['editor']){
246
+ this.parent.editor.createItem( _value );
247
+ }
248
+ }
249
+ else {
250
+ _value = COMM.Values.clone( this.value );
251
+ this._setValueTop( _value );
252
+ this._setValueBottom( _value );
253
+ if(this.parent['editor']){
254
+ this.parent.editor.modifyItem( _value );
255
+ }
256
+ }
257
+ this.setValue( _value );
258
+ this.dragMode = 'normal';
259
+ return true;
260
+ },
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
+
286
+ /** = Description
287
+ * Refreshes the object's label and place on the HTimeSheet.
288
+ *
289
+ **/
290
+ refreshValue: function(){
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 );
303
+ this.drawRect();
304
+ }
305
+ }
306
+ });
307
+
308
+