]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/Web/Javascripts/source/prado/controls/controls.js
8ea6afe36bab14f9bb4a15d16fe3bc0f8e0106a7
[bacula/bacula] / gui / baculum / framework / Web / Javascripts / source / prado / controls / controls.js
1 Prado.WebUI = Class.create();
2
3 Prado.WebUI.Control = Class.create({
4
5         initialize : function(options)
6         {
7             this.registered = false;
8                 this.ID = options.ID;
9                 this.element = $(this.ID);
10                 this.observers = new Array();
11                 this.intervals = new Array();
12                 var e;
13                 if (e = Prado.Registry.get(this.ID))
14                         this.replace(e, options);
15                 else
16                         this.register(options);
17
18                 if (this === Prado.Registry.get(this.ID))
19                 {
20                         this.registered = true;
21                         if(this.onInit)
22                                 this.onInit(options);
23                 }
24         },
25
26         /**
27          * Registers the control wrapper in the Prado client side control registry
28          * @param array control wrapper options
29          */
30         register : function(options)
31         {
32                 return Prado.Registry.set(options.ID, this);
33         },
34
35         /**
36          * De-registers the control wrapper in the Prado client side control registry
37          */
38         deregister : function()
39         {
40                 // extra check so we don't ever deregister another wrapper
41                 if (Prado.Registry.get(this.ID)===this)
42                         return Prado.Registry.unset(this.ID);
43                 else
44                         debugger; // invoke debugger - this should never happen
45         },
46
47         /**
48          * Replaces and control wrapper for an already existing control in the Prado client side control registry
49          * @param object reference to the old wrapper
50          * @param array control wrapper options
51          */
52         replace : function(oldwrapper, options)
53         {
54                 // if there's some advanced state management in the wrapper going on, then
55                 // this method could be used either to copy the current state of the control
56                 // from the old wrapper to this new one (which then could live on, while the old
57                 // one could get destroyed), or to copy the new, changed options to the old wrapper,
58                 // (which could then left intact to keep working, while this new wrapper could be
59                 // disposed of by exiting its initialization without installing any handlers or 
60                 // leaving any references to it)
61                 //
62
63                 // for now this method is simply deinitializing and deregistering the old wrapper, 
64                 // and then registering the new wrapper for the control id
65
66                 if (oldwrapper.deinitialize)
67                         oldwrapper.deinitialize();
68
69                 return this.register(options);
70         },
71
72         /**
73          * Registers an event observer which will be automatically disposed of when the wrapper 
74          * is deregistered
75          * @param element DOM element reference or id to attach the event handler to
76          * @param string event name to observe
77          * @param handler event handler function
78          */
79         observe: function(element, eventName, handler)
80         {
81                 var e = { _element: element, _eventName: eventName, _handler: handler };
82                 this.observers.push(e);
83                 return Event.observe(e._element,e._eventName,e._handler);
84         },
85
86         /**
87          * Checks whether an event observer is installed and returns its index
88          * @param element DOM element reference or id the event handler was attached to
89          * @param string event name observed
90          * @param handler event handler function
91          * @result int false if the event handler is not installed, or 1-based index when installed
92          */
93         findObserver: function(element, eventName, handler)
94         {
95                 var e = { _element: element, _eventName: eventName, _handler: handler };
96                 var idx = -1;
97                 for(var i=0;i<this.observers.length;i++)
98                 {       
99                         var o = this.observers[i];
100                         if ((o._element===element) && (o._eventName===eventName) && (o._handler===handler))
101                         {
102                                 idx = i;
103                                 break;
104                         }
105                 }
106                 return idx;
107         },
108         
109
110         /**
111          * Degisters an event observer from the list of automatically disposed handlers
112          * @param element DOM element reference or id the event handler was attached to
113          * @param string event name observed
114          * @param handler event handler function
115          */
116         stopObserving: function(element, eventName, handler)
117         {
118                 var idx = this.findObserver(element,eventName,handler);
119                 if (idx!=-1)
120                         this.observers = this.observers.without(this.observers[idx]);
121                 else
122                         debugger; // shouldn't happen
123
124                 return Event.stopObserving(element,eventName,handler);
125         },
126
127         /**
128          * Registers a code snippet or function to be executed after a delay, if the
129          * wrapper hasn't been destroyed in the meantime
130          * @param code function or code snippet to execute
131          * @param int number of milliseconds to wait before executing
132          * @return int unique ID that can be used to cancel the scheduled execution 
133          */
134         setTimeout: function(func, delay)
135         {
136                 if (!Object.isFunction(func)) 
137                 {
138                         var expr = func;
139                         func = function() { return eval(expr); }
140                 };
141                 var obj = this;
142                 return window.setTimeout(function() {
143                         if (!obj.isLingering())
144                                 func();
145                         obj = null;
146                 },delay);
147         },
148
149         /**
150          * Cancels a previously scheduled code snippet or function
151          * @param int unique ID returned by setTimeout()
152          */
153         clearTimeout: function(timeoutid)
154         {
155                 return window.clearTimeout(timeoutid);
156         },
157
158         /**
159          * Registers a code snippet or function to be executed periodically, up until the
160          * wrapper gets destroyed or the schedule cancelled using cancelInterval()
161          * @param code function or code snippet to execute
162          * @param int number of milliseconds to wait before executing
163          * @return int unique ID that can be used to cancel the interval (see clearInterval() method)
164          */
165         setInterval: function(func, delay)
166         {
167                 if (!Object.isFunction(func)) func = function() { eval(func); };
168                 var obj = this;
169                 var h = window.setInterval(function() {
170                         if (!obj.isLingering())
171                                 func();
172                 },delay);
173                 this.intervals.push(h);
174                 return h;
175         },
176
177         /**
178          * Deregisters a snipper or function previously registered with setInterval()
179          * @param int unique ID of interval (returned by setInterval() previously)
180          */
181         clearInterval: function(intervalid)
182         {
183                 window.clearInterval(intervalid);
184                 this.intervals = this.intervals.without(intervalid);
185         },
186
187         /**
188          * Tells whether this is a wrapper that has already been deregistered and is lingering
189          * @return bool true if object
190          */
191         isLingering: function()
192         {
193                 return !this.registered;
194         },
195
196         /**
197          * Deinitializes the control wrapper by calling the onDone method and the deregistering it
198          * @param array control wrapper options
199          */
200         deinitialize : function()
201         {
202                 if (this.registered)
203                         {
204                                 if(this.onDone)
205                                         this.onDone();
206
207                                 // automatically stop all intervals
208                                 while (this.intervals.length>0) 
209                                         window.clearInterval(this.intervals.pop());
210
211                                 // automatically deregister all installed observers
212                                 while (this.observers.length>0) 
213                                 {
214                                         var e = this.observers.pop();
215                                         Event.stopObserving(e._element,e._eventName,e._handler);
216                                 }
217                         }
218                 else
219                         debugger; // shouldn't happen
220
221                 this.deregister();
222
223                 this.registered = false;
224         }
225
226 });
227
228 Prado.WebUI.PostBackControl = Class.create(Prado.WebUI.Control, {
229
230         onInit : function(options)
231         {
232                 this._elementOnClick = null;
233
234                 if (!this.element) 
235                         debugger; // element not found
236                 else
237                         {
238                                 //capture the element's onclick function
239                                 if(typeof(this.element.onclick)=="function")
240                                 {
241                                         this._elementOnClick = this.element.onclick.bind(this.element);
242                                         this.element.onclick = null;
243                                 }
244                                 this.observe(this.element, "click", this.elementClicked.bindEvent(this,options));
245                         }
246         },
247
248         elementClicked : function(event, options)
249         {
250                 var src = Event.element(event);
251                 var doPostBack = true;
252                 var onclicked = null;
253
254                 if(this._elementOnClick)
255                 {
256                         var onclicked = this._elementOnClick(event);
257                         if(typeof(onclicked) == "boolean")
258                                 doPostBack = onclicked;
259                 }
260                 if(doPostBack && !Prado.Element.isDisabled(src))
261                         this.onPostBack(event,options);
262                 if(typeof(onclicked) == "boolean" && !onclicked)
263                         Event.stop(event);
264         },
265
266         onPostBack : function(event, options)
267         {
268                 Prado.PostBack(event,options);
269         }
270
271 });
272
273 Prado.WebUI.TButton = Class.create(Prado.WebUI.PostBackControl);
274 Prado.WebUI.TLinkButton = Class.create(Prado.WebUI.PostBackControl);
275 Prado.WebUI.TCheckBox = Class.create(Prado.WebUI.PostBackControl);
276 Prado.WebUI.TBulletedList = Class.create(Prado.WebUI.PostBackControl);
277 Prado.WebUI.TImageMap = Class.create(Prado.WebUI.PostBackControl);
278
279 /**
280  * TImageButton client-side behaviour. With validation, Firefox needs
281  * to capture the x,y point of the clicked image in hidden form fields.
282  */
283 Prado.WebUI.TImageButton = Class.create(Prado.WebUI.PostBackControl, 
284 {
285         /**
286          * Override parent onPostBack function, tried to add hidden forms
287          * inputs to capture x,y clicked point.
288          */
289         onPostBack : function(event, options)
290         {
291                 this.addXYInput(event,options);
292                 Prado.PostBack(event, options);
293                 this.removeXYInput(event,options);
294         },
295
296         /**
297          * Add hidden inputs to capture the x,y point clicked on the image.
298          * @param event DOM click event.
299          * @param array image button options.
300          */
301         addXYInput : function(event,options)
302         {
303                 var imagePos = this.element.cumulativeOffset();
304                 var clickedPos = [event.clientX, event.clientY];
305                 var x = clickedPos[0]-imagePos[0]+1;
306                 var y = clickedPos[1]-imagePos[1]+1;
307                 x = x < 0 ? 0 : x;
308                 y = y < 0 ? 0 : y;
309                 var id = options['EventTarget'];
310                 var x_input = $(id+"_x");
311                 var y_input = $(id+"_y");
312                 if(x_input)
313                 {
314                         x_input.value = x;
315                 }
316                 else
317                 {
318                         x_input = INPUT({type:'hidden',name:id+'_x','id':id+'_x',value:x});
319                         this.element.parentNode.appendChild(x_input);
320                 }
321                 if(y_input)
322                 {
323                         y_input.value = y;
324                 }
325                 else
326                 {
327                         y_input = INPUT({type:'hidden',name:id+'_y','id':id+'_y',value:y});
328                         this.element.parentNode.appendChild(y_input);
329                 }
330         },
331
332         /**
333          * Remove hidden inputs for x,y-click capturing
334          * @param event DOM click event.
335          * @param array image button options.
336          */
337         removeXYInput : function(event,options)
338         {
339                 var id = options['EventTarget'];
340                 this.element.parentNode.removeChild($(id+"_x"));
341                 this.element.parentNode.removeChild($(id+"_y"));
342         }
343 });
344
345
346 /**
347  * Radio button, only initialize if not already checked.
348  */
349 Prado.WebUI.TRadioButton = Class.create(Prado.WebUI.PostBackControl,
350 {
351         initialize : function($super, options)
352         {
353                 this.element = $(options['ID']);
354                 if(this.element)
355                 {
356                         if(!this.element.checked)
357                                 $super(options);
358                 }
359         }
360 });
361
362
363 Prado.WebUI.TTextBox = Class.create(Prado.WebUI.PostBackControl,
364 {
365         onInit : function(options)
366         {
367                 this.options=options;
368                 if(this.options['TextMode'] != 'MultiLine')
369                         this.observe(this.element, "keydown", this.handleReturnKey.bind(this));
370                 if(this.options['AutoPostBack']==true)
371                         this.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
372         },
373
374         handleReturnKey : function(e)
375         {
376                  if(Event.keyCode(e) == Event.KEY_RETURN)
377         {
378                         var target = Event.element(e);
379                         if(target)
380                         {
381                                 if(this.options['AutoPostBack']==true)
382                                 {
383                                         Event.fireEvent(target, "change");
384                                         Event.stop(e);
385                                 }
386                                 else
387                                 {
388                                         if(this.options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
389                                         {
390                                                 if(!Prado.Validation.validate(this.options['FormID'], this.options['ValidationGroup'], $(this.options['ID'])))
391                                                         return Event.stop(e);
392                                         }
393                                 }
394                         }
395                 }
396         }
397 });
398
399 Prado.WebUI.TListControl = Class.create(Prado.WebUI.PostBackControl,
400 {
401         onInit : function(options)
402         {
403                 this.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
404         }
405 });
406
407 Prado.WebUI.TListBox = Class.create(Prado.WebUI.TListControl);
408 Prado.WebUI.TDropDownList = Class.create(Prado.WebUI.TListControl);
409
410 Prado.WebUI.DefaultButton = Class.create(Prado.WebUI.Control,
411 {
412         onInit : function(options)
413         {
414                 this.options = options;
415                 this.observe(options['Panel'], 'keydown', this.triggerEvent.bindEvent(this));
416         },
417
418         triggerEvent : function(ev, target)
419         {
420                 var enterPressed = Event.keyCode(ev) == Event.KEY_RETURN;
421                 var isTextArea = Event.element(ev).tagName.toLowerCase() == "textarea";
422                 var isHyperLink = Event.element(ev).tagName.toLowerCase() == "a" && Event.element(ev).hasAttribute("href");
423                 var isValidButton = Event.element(ev).tagName.toLowerCase() == "input" &&  Event.element(ev).type.toLowerCase() == "submit";
424                 
425                 if(enterPressed && !isTextArea && !isValidButton && !isHyperLink)
426                 {
427                         var defaultButton = $(this.options['Target']);
428                         if(defaultButton)
429                         {
430                                 this.triggered = true;
431                                 Event.fireEvent(defaultButton, this.options['Event']);
432                                 Event.stop(ev);
433                         }
434                 }
435         }
436 });
437
438 Prado.WebUI.TTextHighlighter = Class.create();
439 Prado.WebUI.TTextHighlighter.prototype =
440 {
441         initialize:function(id)
442         {
443                 if(!window.clipboardData) return;
444                 var options =
445                 {
446                         href : 'javascript:;/'+'/copy code to clipboard',
447                         onclick : 'Prado.WebUI.TTextHighlighter.copy(this)',
448                         onmouseover : 'Prado.WebUI.TTextHighlighter.hover(this)',
449                         onmouseout : 'Prado.WebUI.TTextHighlighter.out(this)'
450                 }
451                 var div = DIV({className:'copycode'}, A(options, 'Copy Code'));
452                 document.write(DIV(null,div).innerHTML);
453         }
454 };
455
456 Object.extend(Prado.WebUI.TTextHighlighter,
457 {
458         copy : function(obj)
459         {
460                 var parent = obj.parentNode.parentNode.parentNode;
461                 var text = '';
462                 for(var i = 0; i < parent.childNodes.length; i++)
463                 {
464                         var node = parent.childNodes[i];
465                         if(node.innerText)
466                                 text += node.innerText == 'Copy Code' ? '' : node.innerText;
467                         else
468                                 text += node.nodeValue;
469                 }
470                 if(text.length > 0)
471                         window.clipboardData.setData("Text", text);
472         },
473
474         hover : function(obj)
475         {
476                 obj.parentNode.className = "copycode copycode_hover";
477         },
478
479         out : function(obj)
480         {
481                 obj.parentNode.className = "copycode";
482         }
483 });
484
485
486 Prado.WebUI.TCheckBoxList = Base.extend(
487 {
488         constructor : function(options)
489         {
490                 Prado.Registry.set(options.ListID, this);
491                 for(var i = 0; i<options.ItemCount; i++)
492                 {
493                         var checkBoxOptions = Object.extend(
494                         {
495                                 ID : options.ListID+"_c"+i,
496                                 EventTarget : options.ListName+"$c"+i
497                         }, options);
498                         new Prado.WebUI.TCheckBox(checkBoxOptions);
499                 }
500         }
501 });
502
503 Prado.WebUI.TRadioButtonList = Base.extend(
504 {
505         constructor : function(options)
506         {
507                 Prado.Registry.set(options.ListID, this);
508                 for(var i = 0; i<options.ItemCount; i++)
509                 {
510                         var radioButtonOptions = Object.extend(
511                         {
512                                 ID : options.ListID+"_c"+i,
513                                 EventTarget : options.ListName+"$c"+i
514                         }, options);
515                         new Prado.WebUI.TRadioButton(radioButtonOptions);
516                 }
517         }
518 });