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