Merge "Add qtip job to pod zte-virtual6"
[releng.git] / utils / test / reporting / 3rd_party / js / util.js
1 (function($) {\r
2 \r
3         /**\r
4          * Generate an indented list of links from a nav. Meant for use with panel().\r
5          * @return {jQuery} jQuery object.\r
6          */\r
7         $.fn.navList = function() {\r
8 \r
9                 var     $this = $(this);\r
10                         $a = $this.find('a'),\r
11                         b = [];\r
12 \r
13                 $a.each(function() {\r
14 \r
15                         var     $this = $(this),\r
16                                 indent = Math.max(0, $this.parents('li').length - 1),\r
17                                 href = $this.attr('href'),\r
18                                 target = $this.attr('target');\r
19 \r
20                         b.push(\r
21                                 '<a ' +\r
22                                         'class="link depth-' + indent + '"' +\r
23                                         ( (typeof target !== 'undefined' && target != '') ? ' target="' + target + '"' : '') +\r
24                                         ( (typeof href !== 'undefined' && href != '') ? ' href="' + href + '"' : '') +\r
25                                 '>' +\r
26                                         '<span class="indent-' + indent + '"></span>' +\r
27                                         $this.text() +\r
28                                 '</a>'\r
29                         );\r
30 \r
31                 });\r
32 \r
33                 return b.join('');\r
34 \r
35         };\r
36 \r
37         /**\r
38          * Panel-ify an element.\r
39          * @param {object} userConfig User config.\r
40          * @return {jQuery} jQuery object.\r
41          */\r
42         $.fn.panel = function(userConfig) {\r
43 \r
44                 // No elements?\r
45                         if (this.length == 0)\r
46                                 return $this;\r
47 \r
48                 // Multiple elements?\r
49                         if (this.length > 1) {\r
50 \r
51                                 for (var i=0; i < this.length; i++)\r
52                                         $(this[i]).panel(userConfig);\r
53 \r
54                                 return $this;\r
55 \r
56                         }\r
57 \r
58                 // Vars.\r
59                         var     $this = $(this),\r
60                                 $body = $('body'),\r
61                                 $window = $(window),\r
62                                 id = $this.attr('id'),\r
63                                 config;\r
64 \r
65                 // Config.\r
66                         config = $.extend({\r
67 \r
68                                 // Delay.\r
69                                         delay: 0,\r
70 \r
71                                 // Hide panel on link click.\r
72                                         hideOnClick: false,\r
73 \r
74                                 // Hide panel on escape keypress.\r
75                                         hideOnEscape: false,\r
76 \r
77                                 // Hide panel on swipe.\r
78                                         hideOnSwipe: false,\r
79 \r
80                                 // Reset scroll position on hide.\r
81                                         resetScroll: false,\r
82 \r
83                                 // Reset forms on hide.\r
84                                         resetForms: false,\r
85 \r
86                                 // Side of viewport the panel will appear.\r
87                                         side: null,\r
88 \r
89                                 // Target element for "class".\r
90                                         target: $this,\r
91 \r
92                                 // Class to toggle.\r
93                                         visibleClass: 'visible'\r
94 \r
95                         }, userConfig);\r
96 \r
97                         // Expand "target" if it's not a jQuery object already.\r
98                                 if (typeof config.target != 'jQuery')\r
99                                         config.target = $(config.target);\r
100 \r
101                 // Panel.\r
102 \r
103                         // Methods.\r
104                                 $this._hide = function(event) {\r
105 \r
106                                         // Already hidden? Bail.\r
107                                                 if (!config.target.hasClass(config.visibleClass))\r
108                                                         return;\r
109 \r
110                                         // If an event was provided, cancel it.\r
111                                                 if (event) {\r
112 \r
113                                                         event.preventDefault();\r
114                                                         event.stopPropagation();\r
115 \r
116                                                 }\r
117 \r
118                                         // Hide.\r
119                                                 config.target.removeClass(config.visibleClass);\r
120 \r
121                                         // Post-hide stuff.\r
122                                                 window.setTimeout(function() {\r
123 \r
124                                                         // Reset scroll position.\r
125                                                                 if (config.resetScroll)\r
126                                                                         $this.scrollTop(0);\r
127 \r
128                                                         // Reset forms.\r
129                                                                 if (config.resetForms)\r
130                                                                         $this.find('form').each(function() {\r
131                                                                                 this.reset();\r
132                                                                         });\r
133 \r
134                                                 }, config.delay);\r
135 \r
136                                 };\r
137 \r
138                         // Vendor fixes.\r
139                                 $this\r
140                                         .css('-ms-overflow-style', '-ms-autohiding-scrollbar')\r
141                                         .css('-webkit-overflow-scrolling', 'touch');\r
142 \r
143                         // Hide on click.\r
144                                 if (config.hideOnClick) {\r
145 \r
146                                         $this.find('a')\r
147                                                 .css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');\r
148 \r
149                                         $this\r
150                                                 .on('click', 'a', function(event) {\r
151 \r
152                                                         var $a = $(this),\r
153                                                                 href = $a.attr('href'),\r
154                                                                 target = $a.attr('target');\r
155 \r
156                                                         if (!href || href == '#' || href == '' || href == '#' + id)\r
157                                                                 return;\r
158 \r
159                                                         // Cancel original event.\r
160                                                                 event.preventDefault();\r
161                                                                 event.stopPropagation();\r
162 \r
163                                                         // Hide panel.\r
164                                                                 $this._hide();\r
165 \r
166                                                         // Redirect to href.\r
167                                                                 window.setTimeout(function() {\r
168 \r
169                                                                         if (target == '_blank')\r
170                                                                                 window.open(href);\r
171                                                                         else\r
172                                                                                 window.location.href = href;\r
173 \r
174                                                                 }, config.delay + 10);\r
175 \r
176                                                 });\r
177 \r
178                                 }\r
179 \r
180                         // Event: Touch stuff.\r
181                                 $this.on('touchstart', function(event) {\r
182 \r
183                                         $this.touchPosX = event.originalEvent.touches[0].pageX;\r
184                                         $this.touchPosY = event.originalEvent.touches[0].pageY;\r
185 \r
186                                 })\r
187 \r
188                                 $this.on('touchmove', function(event) {\r
189 \r
190                                         if ($this.touchPosX === null\r
191                                         ||      $this.touchPosY === null)\r
192                                                 return;\r
193 \r
194                                         var     diffX = $this.touchPosX - event.originalEvent.touches[0].pageX,\r
195                                                 diffY = $this.touchPosY - event.originalEvent.touches[0].pageY,\r
196                                                 th = $this.outerHeight(),\r
197                                                 ts = ($this.get(0).scrollHeight - $this.scrollTop());\r
198 \r
199                                         // Hide on swipe?\r
200                                                 if (config.hideOnSwipe) {\r
201 \r
202                                                         var result = false,\r
203                                                                 boundary = 20,\r
204                                                                 delta = 50;\r
205 \r
206                                                         switch (config.side) {\r
207 \r
208                                                                 case 'left':\r
209                                                                         result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta);\r
210                                                                         break;\r
211 \r
212                                                                 case 'right':\r
213                                                                         result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta));\r
214                                                                         break;\r
215 \r
216                                                                 case 'top':\r
217                                                                         result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY > delta);\r
218                                                                         break;\r
219 \r
220                                                                 case 'bottom':\r
221                                                                         result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY < (-1 * delta));\r
222                                                                         break;\r
223 \r
224                                                                 default:\r
225                                                                         break;\r
226 \r
227                                                         }\r
228 \r
229                                                         if (result) {\r
230 \r
231                                                                 $this.touchPosX = null;\r
232                                                                 $this.touchPosY = null;\r
233                                                                 $this._hide();\r
234 \r
235                                                                 return false;\r
236 \r
237                                                         }\r
238 \r
239                                                 }\r
240 \r
241                                         // Prevent vertical scrolling past the top or bottom.\r
242                                                 if (($this.scrollTop() < 0 && diffY < 0)\r
243                                                 || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {\r
244 \r
245                                                         event.preventDefault();\r
246                                                         event.stopPropagation();\r
247 \r
248                                                 }\r
249 \r
250                                 });\r
251 \r
252                         // Event: Prevent certain events inside the panel from bubbling.\r
253                                 $this.on('click touchend touchstart touchmove', function(event) {\r
254                                         event.stopPropagation();\r
255                                 });\r
256 \r
257                         // Event: Hide panel if a child anchor tag pointing to its ID is clicked.\r
258                                 $this.on('click', 'a[href="#' + id + '"]', function(event) {\r
259 \r
260                                         event.preventDefault();\r
261                                         event.stopPropagation();\r
262 \r
263                                         config.target.removeClass(config.visibleClass);\r
264 \r
265                                 });\r
266 \r
267                 // Body.\r
268 \r
269                         // Event: Hide panel on body click/tap.\r
270                                 $body.on('click touchend', function(event) {\r
271                                         $this._hide(event);\r
272                                 });\r
273 \r
274                         // Event: Toggle.\r
275                                 $body.on('click', 'a[href="#' + id + '"]', function(event) {\r
276 \r
277                                         event.preventDefault();\r
278                                         event.stopPropagation();\r
279 \r
280                                         config.target.toggleClass(config.visibleClass);\r
281 \r
282                                 });\r
283 \r
284                 // Window.\r
285 \r
286                         // Event: Hide on ESC.\r
287                                 if (config.hideOnEscape)\r
288                                         $window.on('keydown', function(event) {\r
289 \r
290                                                 if (event.keyCode == 27)\r
291                                                         $this._hide(event);\r
292 \r
293                                         });\r
294 \r
295                 return $this;\r
296 \r
297         };\r
298 \r
299         /**\r
300          * Apply "placeholder" attribute polyfill to one or more forms.\r
301          * @return {jQuery} jQuery object.\r
302          */\r
303         $.fn.placeholder = function() {\r
304 \r
305                 // Browser natively supports placeholders? Bail.\r
306                         if (typeof (document.createElement('input')).placeholder != 'undefined')\r
307                                 return $(this);\r
308 \r
309                 // No elements?\r
310                         if (this.length == 0)\r
311                                 return $this;\r
312 \r
313                 // Multiple elements?\r
314                         if (this.length > 1) {\r
315 \r
316                                 for (var i=0; i < this.length; i++)\r
317                                         $(this[i]).placeholder();\r
318 \r
319                                 return $this;\r
320 \r
321                         }\r
322 \r
323                 // Vars.\r
324                         var $this = $(this);\r
325 \r
326                 // Text, TextArea.\r
327                         $this.find('input[type=text],textarea')\r
328                                 .each(function() {\r
329 \r
330                                         var i = $(this);\r
331 \r
332                                         if (i.val() == ''\r
333                                         ||  i.val() == i.attr('placeholder'))\r
334                                                 i\r
335                                                         .addClass('polyfill-placeholder')\r
336                                                         .val(i.attr('placeholder'));\r
337 \r
338                                 })\r
339                                 .on('blur', function() {\r
340 \r
341                                         var i = $(this);\r
342 \r
343                                         if (i.attr('name').match(/-polyfill-field$/))\r
344                                                 return;\r
345 \r
346                                         if (i.val() == '')\r
347                                                 i\r
348                                                         .addClass('polyfill-placeholder')\r
349                                                         .val(i.attr('placeholder'));\r
350 \r
351                                 })\r
352                                 .on('focus', function() {\r
353 \r
354                                         var i = $(this);\r
355 \r
356                                         if (i.attr('name').match(/-polyfill-field$/))\r
357                                                 return;\r
358 \r
359                                         if (i.val() == i.attr('placeholder'))\r
360                                                 i\r
361                                                         .removeClass('polyfill-placeholder')\r
362                                                         .val('');\r
363 \r
364                                 });\r
365 \r
366                 // Password.\r
367                         $this.find('input[type=password]')\r
368                                 .each(function() {\r
369 \r
370                                         var i = $(this);\r
371                                         var x = $(\r
372                                                                 $('<div>')\r
373                                                                         .append(i.clone())\r
374                                                                         .remove()\r
375                                                                         .html()\r
376                                                                         .replace(/type="password"/i, 'type="text"')\r
377                                                                         .replace(/type=password/i, 'type=text')\r
378                                         );\r
379 \r
380                                         if (i.attr('id') != '')\r
381                                                 x.attr('id', i.attr('id') + '-polyfill-field');\r
382 \r
383                                         if (i.attr('name') != '')\r
384                                                 x.attr('name', i.attr('name') + '-polyfill-field');\r
385 \r
386                                         x.addClass('polyfill-placeholder')\r
387                                                 .val(x.attr('placeholder')).insertAfter(i);\r
388 \r
389                                         if (i.val() == '')\r
390                                                 i.hide();\r
391                                         else\r
392                                                 x.hide();\r
393 \r
394                                         i\r
395                                                 .on('blur', function(event) {\r
396 \r
397                                                         event.preventDefault();\r
398 \r
399                                                         var x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');\r
400 \r
401                                                         if (i.val() == '') {\r
402 \r
403                                                                 i.hide();\r
404                                                                 x.show();\r
405 \r
406                                                         }\r
407 \r
408                                                 });\r
409 \r
410                                         x\r
411                                                 .on('focus', function(event) {\r
412 \r
413                                                         event.preventDefault();\r
414 \r
415                                                         var i = x.parent().find('input[name=' + x.attr('name').replace('-polyfill-field', '') + ']');\r
416 \r
417                                                         x.hide();\r
418 \r
419                                                         i\r
420                                                                 .show()\r
421                                                                 .focus();\r
422 \r
423                                                 })\r
424                                                 .on('keypress', function(event) {\r
425 \r
426                                                         event.preventDefault();\r
427                                                         x.val('');\r
428 \r
429                                                 });\r
430 \r
431                                 });\r
432 \r
433                 // Events.\r
434                         $this\r
435                                 .on('submit', function() {\r
436 \r
437                                         $this.find('input[type=text],input[type=password],textarea')\r
438                                                 .each(function(event) {\r
439 \r
440                                                         var i = $(this);\r
441 \r
442                                                         if (i.attr('name').match(/-polyfill-field$/))\r
443                                                                 i.attr('name', '');\r
444 \r
445                                                         if (i.val() == i.attr('placeholder')) {\r
446 \r
447                                                                 i.removeClass('polyfill-placeholder');\r
448                                                                 i.val('');\r
449 \r
450                                                         }\r
451 \r
452                                                 });\r
453 \r
454                                 })\r
455                                 .on('reset', function(event) {\r
456 \r
457                                         event.preventDefault();\r
458 \r
459                                         $this.find('select')\r
460                                                 .val($('option:first').val());\r
461 \r
462                                         $this.find('input,textarea')\r
463                                                 .each(function() {\r
464 \r
465                                                         var i = $(this),\r
466                                                                 x;\r
467 \r
468                                                         i.removeClass('polyfill-placeholder');\r
469 \r
470                                                         switch (this.type) {\r
471 \r
472                                                                 case 'submit':\r
473                                                                 case 'reset':\r
474                                                                         break;\r
475 \r
476                                                                 case 'password':\r
477                                                                         i.val(i.attr('defaultValue'));\r
478 \r
479                                                                         x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');\r
480 \r
481                                                                         if (i.val() == '') {\r
482                                                                                 i.hide();\r
483                                                                                 x.show();\r
484                                                                         }\r
485                                                                         else {\r
486                                                                                 i.show();\r
487                                                                                 x.hide();\r
488                                                                         }\r
489 \r
490                                                                         break;\r
491 \r
492                                                                 case 'checkbox':\r
493                                                                 case 'radio':\r
494                                                                         i.attr('checked', i.attr('defaultValue'));\r
495                                                                         break;\r
496 \r
497                                                                 case 'text':\r
498                                                                 case 'textarea':\r
499                                                                         i.val(i.attr('defaultValue'));\r
500 \r
501                                                                         if (i.val() == '') {\r
502                                                                                 i.addClass('polyfill-placeholder');\r
503                                                                                 i.val(i.attr('placeholder'));\r
504                                                                         }\r
505 \r
506                                                                         break;\r
507 \r
508                                                                 default:\r
509                                                                         i.val(i.attr('defaultValue'));\r
510                                                                         break;\r
511 \r
512                                                         }\r
513                                                 });\r
514 \r
515                                 });\r
516 \r
517                 return $this;\r
518 \r
519         };\r
520 \r
521         /**\r
522          * Moves elements to/from the first positions of their respective parents.\r
523          * @param {jQuery} $elements Elements (or selector) to move.\r
524          * @param {bool} condition If true, moves elements to the top. Otherwise, moves elements back to their original locations.\r
525          */\r
526         $.prioritize = function($elements, condition) {\r
527 \r
528                 var key = '__prioritize';\r
529 \r
530                 // Expand $elements if it's not already a jQuery object.\r
531                         if (typeof $elements != 'jQuery')\r
532                                 $elements = $($elements);\r
533 \r
534                 // Step through elements.\r
535                         $elements.each(function() {\r
536 \r
537                                 var     $e = $(this), $p,\r
538                                         $parent = $e.parent();\r
539 \r
540                                 // No parent? Bail.\r
541                                         if ($parent.length == 0)\r
542                                                 return;\r
543 \r
544                                 // Not moved? Move it.\r
545                                         if (!$e.data(key)) {\r
546 \r
547                                                 // Condition is false? Bail.\r
548                                                         if (!condition)\r
549                                                                 return;\r
550 \r
551                                                 // Get placeholder (which will serve as our point of reference for when this element needs to move back).\r
552                                                         $p = $e.prev();\r
553 \r
554                                                         // Couldn't find anything? Means this element's already at the top, so bail.\r
555                                                                 if ($p.length == 0)\r
556                                                                         return;\r
557 \r
558                                                 // Move element to top of parent.\r
559                                                         $e.prependTo($parent);\r
560 \r
561                                                 // Mark element as moved.\r
562                                                         $e.data(key, $p);\r
563 \r
564                                         }\r
565 \r
566                                 // Moved already?\r
567                                         else {\r
568 \r
569                                                 // Condition is true? Bail.\r
570                                                         if (condition)\r
571                                                                 return;\r
572 \r
573                                                 $p = $e.data(key);\r
574 \r
575                                                 // Move element back to its original location (using our placeholder).\r
576                                                         $e.insertAfter($p);\r
577 \r
578                                                 // Unmark element as moved.\r
579                                                         $e.removeData(key);\r
580 \r
581                                         }\r
582 \r
583                         });\r
584 \r
585         };\r
586 \r
587 })(jQuery);