├── .gitignore ├── icon.png ├── icon64.png ├── .jshintignore ├── legacy ├── bugzilla-agile.css ├── bugzilla-treeherder.js ├── bugzilla-git.js ├── bugzilla-agile.js ├── bugzilla-keyboard.js └── jquery.flot.pie.js ├── .editorconfig ├── Makefile ├── .jshintrc ├── options ├── options.js └── options.html ├── js ├── bugzilla-listingpage.js ├── bugzilla-gravatars.js ├── bugzilla-comments.js ├── jquery.scrollTo.js ├── bugzilla-defs.js ├── bugzilla.js ├── bugzilla-images.js ├── bugzilla-misc.js ├── md5.js └── jquery.js ├── manifest.json ├── README.md └── css └── bugzillajs.css /.gitignore: -------------------------------------------------------------------------------- 1 | output/ 2 | \#* 3 | *~ 4 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gkoberger/BugzillaJS/HEAD/icon.png -------------------------------------------------------------------------------- /icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gkoberger/BugzillaJS/HEAD/icon64.png -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | js/jquery* 2 | js/md5.js 3 | js/bugzilla-defs.js 4 | legacy/* 5 | output/** 6 | -------------------------------------------------------------------------------- /legacy/bugzilla-agile.css: -------------------------------------------------------------------------------- 1 | .graph { width: 300px; height: 300px; float: left; } 2 | .graph canvas.overlay { background: none repeat scroll 0 0 rgba(0, 0, 0, 0) !important; } 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | mkdir -p output 3 | zip -r -FS output/bugzillajs.xpi js css icon.png icon64.png manifest.json options/options.js options/options.html 4 | 5 | clean: 6 | mkdir -p output && rm -R output/ 7 | 8 | lint: 9 | jshint . 10 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "camelcase": false, 3 | "curly": true, 4 | "forin": false, 5 | "latedef": "nofunc", 6 | "newcap": false, 7 | "noarg": true, 8 | "nonew": true, 9 | "quotmark": "single", 10 | "undef": true, 11 | "unused": "vars", 12 | "strict": true, 13 | "trailing": true, 14 | "maxlen": 80, 15 | 16 | "eqnull": true, 17 | "esnext": true, 18 | "expr": true, 19 | "globalstrict": true, 20 | 21 | "maxerr": 1000, 22 | "regexdash": true, 23 | "laxcomma": true, 24 | "proto": true, 25 | 26 | "browser": true, 27 | "devel": true, 28 | "nonstandard": true, 29 | "worker": true, 30 | 31 | "-W078": true 32 | } 33 | -------------------------------------------------------------------------------- /options/options.js: -------------------------------------------------------------------------------- 1 | browser.storage.sync.get().then((result) => { 2 | for (let [setting, value] of Object.entries(result)) { 3 | if (!setting.startsWith("settings_")) { 4 | continue; 5 | } 6 | let checkbox = document.getElementById(setting.replace(/^settings_/, "")); 7 | if (!checkbox) { 8 | continue; 9 | } 10 | checkbox.checked = value; 11 | } 12 | console.log(result); 13 | }); 14 | 15 | document.getElementById("prefs").addEventListener("change", function onChange(event) { 16 | let setting_name = 'settings_' + event.target.id; 17 | browser.storage.sync.set({ 18 | [setting_name]: event.target.checked, 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /js/bugzilla-listingpage.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, $ */ 4 | 5 | registerPref('openall', {'title': 'Option to open all bugs in tabs', 6 | 'setting_default': true, 7 | 'callback': loadOpenAll, 8 | 'category': 'listings'}); 9 | 10 | function loadOpenAll() { 11 | var openAll = function(e) { 12 | e.preventDefault(); 13 | 14 | var all = $('.bz_id_column a'); 15 | var msg = 'You\'re trying to open ' + all.length + ' tabs. '; 16 | msg += 'Are you sure you want to do this?'; 17 | if (all.length < 10 || confirm(msg)) { 18 | $('.bz_id_column a').each(function() { 19 | if ($(this).attr('href')) { 20 | window.open($(this).attr('href'), '_blank'); 21 | } 22 | }); 23 | } 24 | }; 25 | 26 | var a = $('', {'href': '#', 27 | 'click': openAll, 28 | 'text': 'Open All in Tabs'}), 29 | td = $(''); 30 | 31 | td.append(a); 32 | $('.bz_query_edit').before(td); 33 | } 34 | -------------------------------------------------------------------------------- /js/bugzilla-gravatars.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, ifBug, hex_md5 */ 4 | 5 | registerPref('gravatar', {'title': 'Show gravatars in comments', 6 | 'setting_default': true, 7 | 'callback': ifBug(setGravatars), 8 | 'category': 'inline'}); 9 | 10 | function setGravatars() { 11 | // Some Bugzilla themes have gravatar support 12 | if (document.body.classList.contains('bz_gravatar')) { 13 | return; 14 | } 15 | 16 | var selector = '.bz_comment_head, .bz_first_comment_head'; 17 | var comments = document.querySelectorAll(selector); 18 | for (var i = 0, il = comments.length; i < il; i++) { 19 | var comment = comments[i]; 20 | if (comment.parentNode.classList.contains('ih_history_item')) { 21 | continue; 22 | } 23 | 24 | // Email addresses are only shown if the user is logged in 25 | var emails = comment.querySelectorAll('a.email'); 26 | if (emails.length === 0) { 27 | continue; 28 | } 29 | 30 | var email_node = emails[0]; 31 | var email = email_node.href.substr(7); // removes "mailto:" 32 | // removes + aliases 33 | email = email.toLowerCase().replace(/\+(.*?)@/, '@'); 34 | var hash = memoized_hex_md5(email); 35 | 36 | var img = document.createElement('img'); 37 | img.className = 'gravatar'; 38 | img.src = 'https://secure.gravatar.com/avatar/' + hash; 39 | comment.insertBefore(img, comment.firstChild); 40 | } 41 | } 42 | 43 | var md5_cache = {}; 44 | function memoized_hex_md5(email) { 45 | if (!md5_cache[email]) { 46 | md5_cache[email] = hex_md5(email); 47 | } 48 | 49 | return md5_cache[email]; 50 | } 51 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "BugzillaJS", 4 | "version": "4.2.1", 5 | 6 | "description": "Add features to Bugzilla.", 7 | 8 | "developer": { 9 | "name": "Gregory Koberger, Matthew Noorenberghe", 10 | "url": "https://github.com/gkoberger/BugzillaJS" 11 | }, 12 | 13 | "applications": { 14 | "gecko": { 15 | "id": "jid0-NgMDcEu2B88AbzZ6ulHodW9sJzA@jetpack", 16 | "strict_min_version": "57.0" 17 | } 18 | }, 19 | 20 | "content_scripts": [ 21 | { 22 | "matches": [ 23 | "*://*/", 24 | "*://*/*bug*/", 25 | "*://*/*.cgi*" 26 | ], 27 | "include_globs": [ 28 | "*bugz*", 29 | "*bugs*", 30 | "*Bugs*", 31 | "*bz*" 32 | ], 33 | "css": [ 34 | "css/bugzillajs.css" 35 | ], 36 | "js": [ 37 | "js/jquery.js", 38 | "js/jquery.scrollTo.js", 39 | "js/md5.js", 40 | "js/bugzilla-defs.js", 41 | "js/bugzilla.js", 42 | "js/bugzilla-images.js", 43 | "js/bugzilla-listingpage.js", 44 | "js/bugzilla-gravatars.js", 45 | "js/bugzilla-comments.js", 46 | "js/bugzilla-misc.js" 47 | ] 48 | } 49 | ], 50 | 51 | "icons": { 52 | "32": "icon.png", 53 | "64": "icon64.png" 54 | }, 55 | 56 | "options_ui": { 57 | "page": "options/options.html", 58 | "browser_style": true 59 | }, 60 | 61 | "permissions": [ 62 | "https://api.github.com/*", 63 | "storage" 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /js/bugzilla-comments.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /*global registerPref, ifBug, settings, bz_comments */ 4 | 5 | registerPref('reporter_assignee', 6 | {title: 'Highlight reporter and assignee comments', 7 | callback: ifBug(initHighlightRA), 8 | category: 'comments'}); 9 | 10 | function initHighlightRA() { 11 | if (!settings.reporter_assignee) { 12 | return; 13 | } 14 | 15 | if (document.body.classList.contains('bug_modal')) { 16 | // This feature is already implemented in the BMO experimental modal UI. 17 | return; 18 | } 19 | 20 | var selector = '#bz_assignee_edit_container .vcard .fn'; 21 | var assignee_el = document.querySelector(selector); 22 | if (!assignee_el) { 23 | // The user is probably not logged in 24 | return; 25 | } 26 | var assignee = assignee_el.textContent; 27 | 28 | 29 | var reporter = false; 30 | for (var field of document.querySelectorAll('.field_label')) { 31 | if (field.textContent.includes('Reported')) { 32 | reporter = field.nextElementSibling.querySelector('.vcard .fn'). 33 | textContent; 34 | break; 35 | } 36 | } 37 | 38 | bz_comments.each(function(i, comment) { 39 | var commenter = comment.parentNode.querySelector('.vcard .fn'); 40 | var span; 41 | 42 | if (commenter.textContent == assignee) { 43 | span = document.createElement('span'); 44 | span.textContent = '(assignee)'; 45 | span.classList.add('assignee'); 46 | commenter.parentNode.insertBefore(span, commenter.nextSibling); 47 | } 48 | 49 | if (commenter.textContent == reporter) { 50 | span = document.createElement('span'); 51 | span.textContent = '(reporter)'; 52 | span.classList.add('reporter'); 53 | commenter.parentNode.insertBefore(span, commenter.nextSibling); 54 | } 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /legacy/bugzilla-treeherder.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, ifBug, settings */ 4 | 5 | registerPref('show_treeherder', {'title': 'Show inline Treeherder results', 6 | 'setting_default': true, 7 | 'callback': ifBug(initTreeherder), 8 | 'category': 'bug'}); 9 | 10 | function initTreeherder() { 11 | if (!settings.show_treeherder) { 12 | return; 13 | } 14 | 15 | document.addEventListener('focus', detectIframeFocused); 16 | document.addEventListener('blur', detectIframeFocused); 17 | 18 | var baseHref = 'https://treeherder.mozilla.org/embed/resultset-status/'; 19 | var a_selector = 'a[href^="https://treeherder.mozilla.org/#/jobs?"]'; 20 | var selector = `.bz_comment_text ${a_selector}, .comment-text ${a_selector}`; 21 | var treeherders = document.querySelectorAll(selector); 22 | 23 | for (var i = 0, il = treeherders.length; i < il; i++) { 24 | var treeherder = treeherders[i]; 25 | var href = treeherder.href; 26 | var repo = href.match(/[&?]repo=([\w-]+)/); 27 | var revision = href.match(/[&?]revision=([\w-]+)/); 28 | 29 | if (!repo || !revision) { 30 | continue; 31 | } 32 | 33 | var iframe = document.createElement('iframe'); 34 | iframe.src = baseHref + repo[1] + '/' + revision[1] + '/'; 35 | iframe.classList.add('treeherder_inline_result'); 36 | 37 | treeherder.parentNode.appendChild(iframe); 38 | } 39 | } 40 | 41 | // TODO : https://github.com/gkoberger/BugzillaJS/issues/69 42 | // Once dropping Ominum, do this more properly by including a script in 43 | // the iframes 44 | function detectIframeFocused() { 45 | var iframes = document.getElementsByClassName('iframe_focused'); 46 | if (iframes.length) { 47 | iframes[0].classList.remove('iframe_focused'); 48 | } 49 | 50 | // We need a timeout here, otherwise document.activeElement has not 51 | // changed yet 52 | setTimeout(function() { 53 | if (document.activeElement.nodeName.toLowerCase() == 'iframe') { 54 | document.activeElement.classList.add('iframe_focused'); 55 | } 56 | }, 0); 57 | } 58 | -------------------------------------------------------------------------------- /js/jquery.scrollTo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2007-2014 Ariel Flesler - afleslergmailcom | http://flesler.blogspot.com 3 | * Licensed under MIT 4 | * @author Ariel Flesler 5 | * @version 1.4.14 6 | */ 7 | ;(function(k){'use strict';k(['jquery'],function($){var j=$.scrollTo=function(a,b,c){return $(window).scrollTo(a,b,c)};j.defaults={axis:'xy',duration:0,limit:!0};j.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(f,g,h){if(typeof g=='object'){h=g;g=0}if(typeof h=='function')h={onAfter:h};if(f=='max')f=9e9;h=$.extend({},j.defaults,h);g=g||h.duration;h.queue=h.queue&&h.axis.length>1;if(h.queue)g/=2;h.offset=both(h.offset);h.over=both(h.over);return this._scrollable().each(function(){if(f==null)return;var d=this,$elem=$(d),targ=f,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=win?$(targ):$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}var e=$.isFunction(h.offset)&&h.offset(d,targ)||h.offset;$.each(h.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=j.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(h.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=e[pos]||0;if(h.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*h.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(h.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&h.queue){if(old!=attr[key])animate(h.onAfterFirst);delete attr[key]}});animate(h.onAfter);function animate(a){$elem.animate(attr,g,h.easing,a&&function(){a.call(this,targ,h)})}}).end()};j.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}return j})}(typeof define==='function'&&define.amd?define:function(a,b){if(typeof module!=='undefined'&&module.exports){module.exports=b(require('jquery'))}else{b(jQuery)}})); -------------------------------------------------------------------------------- /js/bugzilla-defs.js: -------------------------------------------------------------------------------- 1 | var categories = {'keyboard': 'Keyboard Shortcuts | To view all keyboard shortcuts, type "?" on any page.', 2 | 'comments': 'Improve Comments | Make the comments on bugs more readable.', 3 | 'inline': 'Show inline media | Show images and other types of content right in the comments.', 4 | 'bug': 'Improve Bugs | These pertain to editing bugs.', 5 | 'listings': 'Listing Pages | These modify parts of the pages with lists of bugs.', 6 | 'misc': 'Miscellaneous | These are other tidbits that do not fit into other categories.'}; 7 | 8 | var tz = {'A':'+1','ADT':'-3','AFT':'+450','AKDT':'-8','AKST':'-9','ALMT':'+6','AMST':'+5','AMST':'-3','AMT':'+4','AMT':'-4','ANAST':'+12','ANAT':'+12','AQTT':'+5','ART':'-3','AST':'-4','AZOST':'0','AZOT':'-1','AZST':'+5','AZT':'+4','B':'+2','BNT':'+8','BOT':'-4','BRST':'-2','BRT':'-3','BST':'+1','BTT':'+6','C':'+3','CAST':'+8','CAT':'+2','CCT':'+650','CDT':'-5','CEST':'+2','CET':'+1','CHADT':'+13:45','CHAST':'+12:45','CKT':'-10','CLST':'-3','CLT':'-4','COT':'-5','CST':'-6','CVT':'-1','CXT':'+7','ChST':'+10','D':'+4','DAVT':'+7','E':'+5','EASST':'-5','EAST':'-6','EAT':'+3','EAT':'+3','ECT':'-5','EDT':'-4','EEST':'+3','EET':'+2','EGST':'0','EGT':'-1','EST':'-5','ET':'-5','F':'+6','FJST':'+13','FJT':'+12','FKST':'-3','FKT':'-4','FNT':'-2','G':'+7','GALT':'-6','GAMT':'-9','GET':'+4','GFT':'-3','GILT':'+12','GMT':0,'GST':'+4','GYT':'-4','H':'+8','HAA':'-3','HAA':'-3','HAC':'-5','HADT':'-9','HAE':'-4','HAE':'-4','HAP':'-7','HAR':'-6','HAST':'-10','HAT':'-250','HAY':'-8','HKT':'+8','HLV':'-450','HNA':'-4','HNA':'-4','HNA':'-4','HNC':'-6','HNC':'-6','HNE':'-5','HNE':'-5','HNE':'-5','HNP':'-8','HNR':'-7','HNT':'-350','HNY':'-9','HOVT':'+7','I':'+9','ICT':'+7','IDT':'+3','IOT':'+6','IRDT':'+450','IRKST':'+9','IRKT':'+8','IRST':'+350','IST':'+2','IST':'+550','IST':'+1','JST':'+9','K':'+10','KGT':'+6','KRAST':'+8','KRAT':'+7','KST':'+9','KUYT':'+4','L':'+11','LHDT':'+11','LHST':'+1050','LINT':'+14','M':'+12','MAGST':'+12','MAGT':'+11','MART':'-950','MAWT':'+5','MDT':'-6','MHT':'+12','MMT':'+650','MSD':'+4','MSK':'+3','MST':'-7','MUT':'+4','MVT':'+5','MYT':'+8','N':'-1','NCT':'+11','NDT':'-250','NFT':'+1150','NOVST':'+7','NOVT':'+6','NPT':'+5:45','NST':'-350','NUT':'-11','NZDT':'+13','NZST':'+12','O':'-2','OMSST':'+7','OMST':'+6','P':'-3','PDT':'-7','PET':'-5','PETST':'+12','PETT':'+12','PGT':'+10','PHOT':'+13','PHT':'+8','PKT':'+5','PMDT':'-2','PMST':'-3','PONT':'+11','PST':'-8','PT':'-8','PWT':'+9','PYST':'-3','PYT':'-4','Q':'-4','R':'-5','RET':'+4','S':'-6','SAMT':'+4','SAST':'+2','SBT':'+11','SCT':'+4','SGT':'+8','SRT':'-3','SST':'-11','T':'-7','TAHT':'-10','TFT':'+5','TJT':'+5','TKT':'-10','TLT':'+9','TMT':'+5','TVT':'+12','U':'-8','ULAT':'+8','UYST':'-2','UYT':'-3','UZT':'+5','V':'-9','VET':'-450','VLAST':'+11','VLAT':'+10','VUT':'+11','W':'-10','WAST':'+2','WAT':'+1','WDT':'+9','WEST':'+1','WEST':'+1','WET':'0','WFT':'+12','WGST':'-2','WGT':'-3','WIB':'+7','WIT':'+9','WITA':'+8','WST':'+1','WST':'+8','WST':'-11','WT':'0','X':'-11','Y':'-12','YAKST':'+10','YAKT':'+9','YAPT':'+10','YEKST':'+6','YEKT':'+5','Z':'0'}; 9 | 10 | -------------------------------------------------------------------------------- /options/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BugzillaJS Options 6 | 7 | 8 |
9 |

Changes take effect on the next load of a Bugzilla page.

10 | 11 | 12 | 13 | 19 | 20 |

Improve Comments

21 |

Make the comments on bugs more readable.

22 |
23 |
24 |
25 |
26 |
27 | 28 |

Show inline media

29 |

Show images and other types of content right in the comments.

30 |
31 |
32 |
33 |
34 |
35 | 36 |

Improve Bugs

37 |

These pertain to editing bugs.

38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 47 |

Listing Pages

48 |

These modify parts of the pages with lists of bugs.

49 |
50 |
51 |
52 | 53 |

Miscellaneous

54 |

These are other tidbits that do not fit into other categories.

55 |
56 |
57 |
58 |
59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DOWNLOAD THE ADD-ON 2 | 3 | https://addons.mozilla.org/firefox/addon/bugzillajs/ 4 | 5 | # DEVELOPING THE ADD-ON 6 | 7 | BugzillaJS is in the process of being converted to a cross-browser web extension, 8 | and can be installed like this: 9 | 10 | git clone git@github.com:gkoberger/BugzillaJS.git bugzillajs 11 | cd bugzillajs 12 | web-ext run 13 | 14 | This should open up an install button in Firefox. 15 | 16 | To package for distribution, simply run `make` 17 | 18 | # TESTING THE ADD-ON 19 | 20 | Once you have it installed, check out the following URL to see it in action: 21 | 22 | https://bugzilla.mozilla.org/show_bug.cgi?id=574290 23 | 24 | # FEATURES 25 | 26 | **This extension was converted to an web extension and is missing some of the 27 | previous features. 28 | If you are interested in these features you can port them from the 'legacy' 29 | directory and submit a PR.** 30 | 31 | You can turn features on and off by clicking the "BugzillaJS Preferences" link 32 | at the top and bottom of every page. You need to refresh the page to see them 33 | come into effect. 34 | 35 | ## Keyboard Shortcuts 36 | To view all keyboard shortcuts, type "?" on any page. 37 | - (Legacy) Enable keyboard shortcuts 38 | 39 | ## Improve Comments 40 | Make the comments on bugs more readable. 41 | - Highlight reporter and assignee comments 42 | - Add scrollbar to overflowing comments 43 | - Hide the first comment if empty 44 | 45 | ## Show inline media 46 | Show images and other types of content right in the comments. 47 | - Display images and attachments as an inline gallery 48 | - Use lightbox for images 49 | - Show GitHub logs inline 50 | - Show gravatars in comments 51 | 52 | ## Improve Bugs 53 | These pertain to editing bugs. 54 | - Style the comments like Github 55 | - Remove flags, status and blocking fields 56 | - Remove access keys 57 | - Don't guess OS and hardware 58 | - Add a "new" link for dependent and blocking fields 59 | - Add a "browse" link for component fields 60 | - (Legacy) Show inline Treeherder results 61 | 62 | ## Listing Pages 63 | These modify parts of the pages with lists of bugs. 64 | - Option to open all bugs in tabs 65 | - (Legacy) Agile Backlog 66 | 67 | ## Miscellaneous 68 | These are other tidbits that do not fit into other categories. 69 | - Makes saved searches into a dropdown (requires Mozilla skin) 70 | 71 | # CONTRIBUTE 72 | 73 | If you have an idea for an extra feature, either ask me to implement it or 74 | you can implement it yourself and submit a patch. I'll do a better job in the 75 | future of cleaning up the code and possibly making it API-like. 76 | 77 | ## Bugzilla Installation URLs 78 | 79 | To test patterns/globs against installation URLs you can visit https://www.bugzilla.org/installation-list/ and run: 80 | ```js 81 | new Set([...document.querySelectorAll("a[href]")].filter(a => a.textContent.trim() == "Bugzilla").map(a => a.href).filter(url => !url.includes("www.bugzilla.org")).filter(url => !url.match(/(.*bugz.*|.*bugs.*|.*Bugs.*|.*bz.*)/))) 82 | ``` 83 | 84 | # TROUBLESHOOTING 85 | 86 | - It conflicts with other Bugzilla extensions and Userscripts. 87 | 88 | ## IF THERE IS A CONFLICT WITH ANOTHER SCRIPT 89 | 90 | Simply disabling the feature in the Bugzilla Preferences should fix it. 91 | 92 | ## STILL HAVE ISSUES? 93 | 94 | Post an issue, or contact me at gkoberger [a] gkoberger [dot] com 95 | -------------------------------------------------------------------------------- /legacy/bugzilla-git.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, ifBug, bz_comments, $, repositionScroll */ 4 | 5 | registerPref('git', {'title': 'Show GitHub logs inline', 6 | 'setting_default': true, 7 | 'callback': ifBug(initGit), 8 | 'category': 'inline'}); 9 | 10 | function initGit() { 11 | var github_regexp = /github.com\/([-\w]*)\/([-\w]*)\/commit\/(\w*)/; 12 | bz_comments.each(function() { 13 | var $comment = $(this); 14 | $('a', $comment).each(function() { 15 | var url = $(this).attr('href'); 16 | var isGithub = url.match(github_regexp); 17 | 18 | if (!isGithub) { 19 | return; 20 | } 21 | 22 | var giturl = 'https://api.github.com/repos/' + isGithub[1] + '/' + 23 | isGithub[2] + '/commits/' + isGithub[3]; 24 | //'?callback=cbk' 25 | 26 | $.getJSON(giturl, function(d) { 27 | var $git = $('
', {'class': 'git-body'}). 28 | insertAfter($comment); 29 | var $head = $('
', {'class': 'git-head'}).appendTo($git); 30 | 31 | $head.append($('

', {'text': d.commit.message})); 32 | 33 | var $span = $(''), 34 | $strong = $('', {'text': d.commit.author.name}), 35 | $date = $('', {'text': d.commit.author.date}); 36 | 37 | $span.append($strong).append($date); 38 | $head.append($span); 39 | 40 | var $table = $('', {'class': 'git'}).appendTo($git); 41 | 42 | $.each(d.files, function(k, file) { 43 | if (file.status === 'added') { 44 | $table.append(''); 48 | } 49 | 50 | if (file.status === 'removed') { 51 | $table.append(''); 55 | } 56 | 57 | if (file.status === 'modified') { 58 | $table.append(''); 63 | } 64 | }); 65 | repositionScroll(); 66 | }); 67 | }); 68 | }); 69 | 70 | function gitBox(added, deleted) { 71 | var output = '
' + added + ' additions & ' + 72 | deleted + ' deletions
'; 73 | 74 | var total = added + deleted; 75 | if (total > 5) { 76 | added = Math.round((added / total) * 5); 77 | deleted = Math.round((deleted / total) * 5); 78 | } 79 | 80 | var t = 0; 81 | var i; 82 | for (i = 0; i < added && t < 5; i++, t++) { 83 | output += ''; 84 | } 85 | for (i = 0; i < deleted && t < 5; i++, t++) { 86 | output += ''; 87 | } 88 | for (i = 0; i < 5 && t < 5; i++, t++) { 89 | output += ''; 90 | } 91 | 92 | return '
' + total + ' ' + 93 | output + '
'; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /js/bugzilla.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* exported bz_comments */ 3 | 4 | /* global $, browser, categories */ 5 | 6 | var settings = [], 7 | settings_fields = [], 8 | bug_id = false, 9 | bz_comments = $('.bz_comment_text:not(#comment_preview_text),' + 10 | '.comment-text:not(#comment-preview)'), 11 | already_run = [], 12 | total_new = 0, 13 | is_mozilla_theme; 14 | 15 | /** Get the bug ID **/ 16 | 17 | bug_id = $('title').text().match(/^(?:Bug )?([0-9]+)/); 18 | bug_id = bug_id ? bug_id[1] : false; 19 | 20 | is_mozilla_theme = document.body.classList.contains('skin-Mozilla'); 21 | 22 | /* Register preferences */ 23 | registerPref('gitcomments', {'title': 'Style the comments like Github', 24 | 'setting_default': true, 25 | 'callback': ifBug(addStyling), 26 | 'category': 'bug'}); 27 | 28 | /** Run the modules **/ 29 | function ifBug(f) { 30 | if (bug_id) { 31 | return f; 32 | } else { 33 | return function() {}; 34 | } 35 | } 36 | 37 | function addStyling() { 38 | if (settings.gitcomments) { 39 | $('body').addClass('git_style'); 40 | $('.git_style .ih_history br').replaceWith('; '); 41 | setTimeout(repositionScroll, 200); 42 | } 43 | } 44 | 45 | function repositionScroll() { 46 | //-- Reposition the scrollTo if necessary 47 | if (location.hash.match(/#c[0-9]*/)) { 48 | $(window).scrollTo($(location.hash)); 49 | } 50 | } 51 | 52 | function registerPref(slug, o) { 53 | /* TODO: integrate these */ 54 | registerPref_old(slug, 55 | o.title, 56 | o.setting_default, 57 | o.callback, 58 | o.category, 59 | o.is_new); 60 | } 61 | 62 | function registerPref_old(slug, 63 | details, 64 | setting_default, 65 | callback, 66 | category, 67 | is_new) { 68 | if (! already_run[slug]) { 69 | if (typeof setting_default == 'function') { 70 | callback = setting_default; 71 | setting_default = null; 72 | } 73 | if (setting_default == null || setting_default === undefined) { 74 | setting_default = true; 75 | } 76 | 77 | callback = callback || function() {}; 78 | 79 | settings[slug] = setting_default; 80 | 81 | browser.storage.sync.get('settings_' + slug).then(function(result) { 82 | var v = result['settings_' + slug]; 83 | var show_new = false; 84 | if (typeof v != 'undefined') { 85 | settings[slug] = v; 86 | } else { 87 | if (is_new) { 88 | total_new++; 89 | notifyNew(); 90 | show_new = true; 91 | } 92 | } 93 | 94 | settings_fields.push({'slug': slug, 95 | 'details': details, 96 | 'is_new': show_new, 97 | 'category': category}); 98 | 99 | // If it's enabled and we're on a Bugzilla page, run it! 100 | if (window.wrappedJSObject.BUGZILLA && settings[slug]) { 101 | callback(); 102 | } 103 | }); 104 | 105 | already_run[slug] = true; 106 | } 107 | } 108 | 109 | function getNotifyElt(prefMenu) { 110 | var notifyElt = prefMenu.nextElementSibling; 111 | if (notifyElt && notifyElt.classList.contains('notify')) { 112 | return notifyElt; 113 | } 114 | 115 | notifyElt = document.createElement('span'); 116 | notifyElt.classList.add('notify'); 117 | return prefMenu.parentNode.insertBefore(notifyElt, 118 | prefMenu.nextElementSibling); 119 | } 120 | 121 | // New feature? Notify them! 122 | function notifyNew() { 123 | if (total_new <= 0) { 124 | return; 125 | } 126 | var prefMenu = document.querySelector('.bjs-prefs'); 127 | var notifyElt = getNotifyElt(prefMenu); 128 | notifyElt.textContent = total_new; 129 | } 130 | -------------------------------------------------------------------------------- /js/bugzilla-images.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, $, _, ifBug, bz_comments */ 4 | 5 | registerPref('gallery', { 6 | 'title': 'Display images and attachments as an inline gallery', 7 | 'setting_default': true, 8 | 'callback': ifNotSecurityBug(initImageInline), 9 | 'category': 'inline'}); 10 | 11 | registerPref('lightbox', { 12 | 'title': 'Use lightbox for images', 13 | 'setting_default': true, 14 | 'callback': ifNotSecurityBug(initImageLightbox), 15 | 'category': 'inline'}); 16 | 17 | function ifNotSecurityBug(func) { 18 | if (document.body.classList.contains('bz_group_websites-security')) { 19 | return function() {}; 20 | } 21 | 22 | return ifBug(func); 23 | } 24 | 25 | var image_attachments = {}, 26 | imageBothRun = false; 27 | 28 | function initImageBoth() { 29 | if (imageBothRun) { 30 | return; 31 | } 32 | imageBothRun = true; 33 | 34 | $('#attachment_table tr, #attachments tr').each(function() { 35 | var $this = $(this); 36 | if ($this.prop('class').match('image')) { 37 | var $a = $this.find('a b').parent(); 38 | $a.addClass('is-image'); 39 | var attachment_id = $a.prop('href').match(/id=([0-9]*)/)[1]; 40 | image_attachments[attachment_id] = $a.prop('href'); 41 | } 42 | }); 43 | 44 | bz_comments.each(function() { 45 | var $comment = $(this); 46 | 47 | $('a', $comment).each(function() { 48 | var $a = $(this); 49 | var attachment_id = $a.prop('name').match('attach_([0-9]+)$'), 50 | is_image_attachment = (attachment_id && 51 | attachment_id[1] in image_attachments); 52 | 53 | /* If it's an image, add the image class */ 54 | if ($a.prop('href').match(/(\.(jpg|gif|png))/i) || 55 | is_image_attachment) { 56 | $a.addClass('is-image'); 57 | $comment.addClass('has-image'); 58 | } 59 | }); 60 | }); 61 | } 62 | 63 | function initImageLightbox() { 64 | initImageBoth(); 65 | 66 | function closeLightbox(e) { 67 | if (e) { 68 | e.preventDefault(); 69 | } 70 | $('.lb, .overlay').remove(); 71 | } 72 | 73 | function bzLightbox(e) { 74 | /* TODO: Fix this! */ 75 | if (e) { 76 | e.preventDefault(); 77 | } 78 | 79 | var $this = $(e.currentTarget); 80 | $(window).trigger('close'); 81 | 82 | var $overlay = $('
').addClass('overlay').appendTo('body'). 83 | css({opacity: 0}); 84 | var $overlay2 = $('
').addClass('overlay2').appendTo('body'); 85 | 86 | $overlay2.css({'top': $(window).scrollTop() + 5}); 87 | 88 | var $img = $('').prop('src', $this.prop('href')).addClass('lb') 89 | .css({'opacity': 0}).appendTo($overlay2); 90 | 91 | $overlay.add($overlay2).click(closeLightbox); 92 | 93 | var $opts = $('
').addClass('opts').appendTo($overlay); 94 | 95 | $opts.append('full image'); 97 | $opts.append(' | close'); 98 | 99 | $('.full_image', $opts).click(function(e) { e.stopPropagation(); }); 100 | $('.close_overlay', $opts).click(function(e) { e.preventDefault(); }); 101 | 102 | $img.css({'opacity': 1}); 103 | $overlay.css({'opacity': 1}); 104 | } 105 | 106 | /* Close on */ 107 | $(window).bind('close', closeLightbox); 108 | 109 | $('#attachment_table, .bz_comment_table, #bugzilla-body') 110 | .delegate('.is-image', 'click', bzLightbox); 111 | } 112 | 113 | function initImageInline() { 114 | initImageBoth(); 115 | 116 | bz_comments.each(function() { 117 | var $comment = $(this); 118 | if (!$comment.hasClass('has-image')) { 119 | return; 120 | } 121 | 122 | var $gal = $('
', {'class': 'img-gal'}).insertAfter($comment); 123 | $comment.find('.is-image').each(function() { 124 | var href = $(this).attr('href'), 125 | $a = $('', {'class': 'preview-img is-image', 'href': href, 126 | 'target': '_blank'}); 127 | $gal.append($a); 128 | 129 | var $img; 130 | if (href.match('^http:')) { // Not https? Blah.. 131 | _.getImage(href, function(src) { 132 | $img = $('', {'src': src}); 133 | $a.append($img); 134 | }); 135 | } else { 136 | $img = $('', {'src': href}); 137 | $a.append($img); 138 | } 139 | 140 | }); 141 | 142 | }); 143 | } 144 | -------------------------------------------------------------------------------- /legacy/bugzilla-agile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, settings, $ */ 4 | 5 | registerPref('agile_backlog', {'title': 'Agile Backlog', 6 | 'setting_default': false, 7 | 'callback': agileBacklog, 8 | 'category': 'listings'}); 9 | 10 | function agileBacklog() { 11 | if (!settings.agile_backlog) { 12 | return; 13 | } 14 | var $wb = $('td.bz_status_whiteboard_column'); 15 | if (!$wb.length) { 16 | return; 17 | } 18 | 19 | var bugs = []; 20 | var components_data = []; 21 | var users_data = []; 22 | var closed_statuses = ['RES', 'VERI']; 23 | var closed_points = 0; 24 | var closed_stories = 0; 25 | var open_points = 0; 26 | var open_stories = 0; 27 | var assigned_points = 0; 28 | var assigned_stories = 0; 29 | var total_stories = 0; 30 | var total_points = 0; 31 | 32 | $wb.each(function() { 33 | total_stories += 1; 34 | var bug = {}; 35 | bug.status = $.trim($(this).siblings('.bz_bug_status_column').text()); 36 | bug.tags = $.trim($(this).text()).split(' '); 37 | bug.elements = []; 38 | 39 | for (var i = 0, j = bug.tags.length; i < j; i++) { 40 | var tokens = bug.tags[i].split('='); 41 | bug.elements[tokens[0]] = tokens[1]; 42 | } 43 | bug.points = 0; 44 | if (bug.elements.p && typeof(parseInt(bug.elements.p, 0)) == 'number') { 45 | bug.points = parseInt(bug.elements.p, 0); 46 | total_points += bug.points; 47 | } 48 | if ($.inArray(bug.status, closed_statuses) > -1) { 49 | closed_stories++; 50 | closed_points += bug.points; 51 | } else { 52 | var assigned_to = $(this).siblings('.bz_assigned_to_column').text(); 53 | if (assigned_to.trim() == 'nobody@mozilla.org') { 54 | open_stories++; 55 | open_points += bug.points; 56 | } else { 57 | assigned_stories++; 58 | assigned_points += bug.points; 59 | } 60 | } 61 | 62 | // build components_data 63 | if (bug.elements.c && bug.elements.c !== '') { 64 | var component = {}, existing_component_idx = -1; 65 | for (i = 0, j = components_data.length; i < j; i++) { 66 | if (bug.elements.c == components_data[i].label) { 67 | existing_component_idx = i; 68 | } 69 | } 70 | if (existing_component_idx > -1) { 71 | component = components_data[existing_component_idx]; 72 | component.data += bug.points; 73 | } else { 74 | component.label = bug.elements.c; 75 | component.data = bug.points; 76 | components_data.push(component); 77 | } 78 | } 79 | 80 | // build users_data 81 | if (bug.elements.u && bug.elements.u !== '') { 82 | var user = {}, existing_user_idx = -1; 83 | for (i = 0, j = users_data.length; i < j; i++) { 84 | if (bug.elements.u == users_data[i].label) { 85 | existing_user_idx = i; 86 | } 87 | } 88 | if (existing_user_idx > -1) { 89 | user = users_data[existing_user_idx]; 90 | user.data += bug.points; 91 | } else { 92 | user.label = bug.elements.u; 93 | user.data = bug.points; 94 | users_data.push(user); 95 | } 96 | } 97 | 98 | bugs.push(bug); 99 | }); 100 | 101 | var $tr = $('
'), 102 | $td1 = $('
' + 45 | '
' + file.filename + 46 | '' + gitBox(5, 0) + 47 | '
' + 52 | '
' + file.filename + 53 | '' + gitBox(0, 5) + 54 | '
' + 59 | '
' + 60 | file.filename + '' + 61 | gitBox(file.additions, file.deletions) + 62 | '
', {'colspan': 99, 'align': 'right'}), 103 | $div = $('
'), 104 | $pointsGraph = $('
', {'id': 'pointsGraph', 'class': 'graph'}), 105 | $componentsGraph = $('
', 106 | {'id': 'componentsGraph', 'class': 'graph'}), 107 | $usersGraph = $('
', {'id': 'usersGraph', 'class': 'graph'}), 108 | 109 | $text = $('
'); 110 | 111 | $text.append($('', {'text': 'Open Stories: ' + open_stories})); 112 | $text.append($('
')); 113 | $text.append($('', 114 | {'text': 'Assigned Stories: ' + assigned_stories})); 115 | $text.append($('
')); 116 | $text.append($('', {'text': 'Closed Stories: ' + closed_stories})); 117 | $text.append($('
')); 118 | $text.append($('', {'text': 'Closed Points: ' + closed_points})); 119 | $text.append($('
')); 120 | $text.append($('', {'text': 'Total Stories: ' + total_stories})); 121 | $text.append($('
')); 122 | $text.append($('', {'text': 'Total Points: ' + total_points})); 123 | 124 | $div.append($pointsGraph); 125 | $div.append($componentsGraph); 126 | $div.append($usersGraph); 127 | $div.append($text); 128 | $td1.append($div); 129 | $tr.append($td1); 130 | 131 | $('table.bz_buglist').append($tr); 132 | 133 | var points_data = [ 134 | {label: 'Open', data: open_points, color: 'rgb(237, 194, 64)'}, 135 | {label: 'Closed', data: closed_points, color: 'rgb(77, 167, 77)'}, 136 | {label: 'Assigned', data: assigned_points, color: 'rgb(175, 216, 248)'} 137 | ]; 138 | var plot_config = {series: {pie: {show: true}}, legend: {show: false}}; 139 | $.plot($('#pointsGraph'), points_data, plot_config); 140 | $.plot($('#componentsGraph'), components_data, plot_config); 141 | $.plot($('#usersGraph'), users_data, plot_config); 142 | console.log('Open Stories: ' + open_stories); 143 | console.log('Open points: ' + open_points); 144 | console.log('Closed Stories: ' + closed_stories); 145 | console.log('Closed points: ' + closed_points); 146 | } 147 | 148 | -------------------------------------------------------------------------------- /js/bugzilla-misc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, ifBug, $, settings, bug_id, is_mozilla_theme */ 4 | 5 | registerPref('commentoverflow', { 6 | 'title': 'Add scrollbar to overflowing comments', 7 | 'setting_default': true, 8 | 'callback': ifBug(commentOverflow), 9 | 'category': 'comments'}); 10 | 11 | registerPref('removeflags', { 12 | 'title': 'Remove flags, status and blocking fields', 13 | 'setting_default': false, 14 | 'callback': ifBug(removeFlags), 15 | 'category': 'bug'}); 16 | 17 | registerPref('removeaccesskeys', { 18 | 'title': 'Remove access keys', 19 | 'setting_default': false, 20 | 'callback': removeAccess, 21 | 'category': 'bug'}); 22 | 23 | registerPref('dontguess', { 24 | 'title': 'Don\'t guess OS and hardware', 25 | 'setting_default': false, 26 | 'callback': dontGuess, 27 | 'category': 'bug'}); 28 | 29 | registerPref('hidefirst', { 30 | 'title': 'Hide the first comment if empty', 31 | 'setting_default': true, 32 | 'callback': ifBug(hideFirst), 33 | 'category': 'comments'}); 34 | 35 | registerPref('relatedbug', { 36 | 'title': 'Add a "new" link for dependent and blocking fields', 37 | 'setting_default': true, 38 | 'callback': ifBug(relatedBug), 39 | 'category': 'bug'}); 40 | 41 | registerPref('browseComponent', { 42 | 'title': 'Add a "browse" link for component fields', 43 | 'setting_default': false, 44 | 'callback': ifBug(browseComponent), 45 | 'category': 'bug'}); 46 | 47 | registerPref('savedSearchDropDown', { 48 | 'title': 'Makes saved searches into a dropdown (requires Mozilla skin)', 49 | 'setting_default': true, 50 | 'callback': savedSearchDropDown, 51 | 'category': 'misc'}); 52 | 53 | 54 | function hideFirst() { 55 | // Hide the first comment if it's blank? 56 | if ($('.bz_first_comment .bz_comment_text').text() === '') { 57 | $('.bz_first_comment').hide(); 58 | $('.bz_comment_table').addClass('no-first-comment'); 59 | } 60 | } 61 | 62 | function commentOverflow() { 63 | // Fix comment overflow 64 | // Idea by fwenzel 65 | $('body').addClass('bzJS-commentoverflow'); 66 | } 67 | 68 | function removeAccess() { 69 | // Remove accessibility keys 70 | // Inspired by jbalogh, who evidently hates accessibility. 71 | $('label[accesskey]').each(function(i, e) { 72 | $(e).removeAttr('accessKey accesskey'); 73 | $(e).addClass('accessKey'); 74 | }); 75 | 76 | $('body').addClass('bzJS-removeaccesskeys'); 77 | } 78 | 79 | function removeFlags() { 80 | // Remove flags 81 | // Idea by jbalogh 82 | $('#flags, .flags_label').remove(); 83 | 84 | $('#bz_show_bug_column_2 [id^=field_label_cf_]').each(function() { 85 | $(this).next().remove(); 86 | $(this).remove(); 87 | }); 88 | } 89 | 90 | function dontGuess() { 91 | if (!location.href.match(/enter_bug/)) { 92 | return; 93 | } 94 | 95 | $('#rep_platform, #op_sys').each(function() { 96 | var $parent = $('', {'css': {'padding-left': 10}}), 97 | $s1 = $('', {'text': '('}), 98 | $a = $('', {'text': 'guess'}), 99 | $s2 = $('', {'text': ')'}); 100 | 101 | $parent.append($s1).append($a).append($s2); 102 | 103 | $a.attr({'href': '#', 'data-val': $(this).val()}); 104 | $a.click(function() { 105 | $(this).closest('td').find('select').val($(this).attr('data-val')); 106 | $(this).parent().hide(); 107 | return false; 108 | }); 109 | $(this).val('All').after($parent); 110 | }); 111 | 112 | $('#os_guess_note').parent().hide(); 113 | } 114 | 115 | function _build_query_string(dict) { 116 | var parts = []; 117 | for (var key in dict) { 118 | parts.push(key + '=' + encodeURIComponent(dict[key])); 119 | } 120 | return parts.join('&'); 121 | } 122 | 123 | function _attachLinkToField(field_id, text, location) { 124 | var fragment = document.createDocumentFragment(); 125 | var link = document.createElement('a'); 126 | link.href = location; 127 | link.appendChild(document.createTextNode(text)); 128 | var span = document.createElement('span'); 129 | span.appendChild(document.createTextNode(' (')); 130 | span.appendChild(link); 131 | span.appendChild(document.createTextNode(')')); 132 | fragment.appendChild(span); 133 | 134 | var parent = document.querySelector('#field-' + field_id + ' .name'); 135 | if (parent) { 136 | // BMO Modal UI 137 | span.style.display = 'block'; 138 | parent.appendChild(fragment); 139 | return; 140 | } 141 | 142 | var field = document.getElementById(field_id); 143 | if (!field) { 144 | return; 145 | } 146 | var text_length = text.length + 3; 147 | field.style.maxWidth = 'calc(100% - ' + text_length + 'ch)'; 148 | 149 | var td = field; 150 | while (td.nodeName.toLowerCase() != 'td') { 151 | td = td.parentNode; 152 | } 153 | td.appendChild(fragment); 154 | } 155 | 156 | function relatedBug() { 157 | if (!settings.relatedbug) { 158 | return; 159 | } 160 | 161 | var prefix = 'enter_bug.cgi?'; 162 | var url_parts = {}; 163 | try { 164 | url_parts.product = document.querySelector('#product option[selected]'). 165 | value; 166 | } catch (ex) { 167 | // The user cannot edit the field or is not logged in 168 | url_parts.product = document.querySelector('#field_container_product') 169 | .textContent; 170 | } 171 | try { 172 | url_parts.component = document 173 | .querySelector('#component option[selected]') 174 | .value; 175 | } catch (ex) { 176 | let comp_text = document.querySelector('#field_container_component') 177 | .firstChild.textContent; 178 | url_parts.component = comp_text.trim().replace(/\)$/, '').trim(); 179 | } 180 | 181 | url_parts.dependson = bug_id; 182 | var new_blocked_bug_location = prefix + _build_query_string(url_parts); 183 | _attachLinkToField('blocked', 'new', new_blocked_bug_location); 184 | 185 | delete url_parts.dependson; 186 | url_parts.blocked = bug_id; 187 | var new_dependson_bug_location = prefix + _build_query_string(url_parts); 188 | _attachLinkToField('dependson', 'new', new_dependson_bug_location); 189 | } 190 | 191 | function browseComponent() { 192 | if (!settings.browseComponent) { 193 | return; 194 | } 195 | var prefix = 'buglist.cgi?'; 196 | var url_parts = {}; 197 | url_parts.product = document.querySelector('#product option[selected]'). 198 | value; 199 | url_parts.component = document.querySelector('#component option[selected]'). 200 | value; 201 | var browse_location = prefix + _build_query_string(url_parts); 202 | 203 | _attachLinkToField('component', 'browse', browse_location); 204 | } 205 | 206 | function savedSearchDropDown() { 207 | if (!is_mozilla_theme) { 208 | return; 209 | } 210 | 211 | var dropdown = document.createElement('li'); 212 | dropdown.className = 'dropdown'; 213 | 214 | var anchor = document.createElement('span'); 215 | anchor.className = 'anchor'; 216 | anchor.textContent = 'Saved Searches'; 217 | dropdown.appendChild(anchor); 218 | 219 | var list = document.createElement('ul'); 220 | var saved = document.querySelectorAll('#links-saved .links li'); 221 | var saved_length = saved.length; 222 | for (var i = 0; i < saved_length; i++) { 223 | list.appendChild(saved[i]); 224 | } 225 | dropdown.appendChild(list); 226 | var topbar = document.querySelector('#header .wrapper > .links'); 227 | topbar.appendChild(dropdown); 228 | document.querySelector('#links-saved').remove(); 229 | } 230 | -------------------------------------------------------------------------------- /legacy/bugzilla-keyboard.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global registerPref, $, _, settings, unsafeWindow */ 4 | 5 | registerPref('keyboard', {'title': 'Enable keyboard shortcuts', 6 | 'setting_default': false, 7 | 'callback': initKB, 8 | 'category': 'keyboard'}); 9 | 10 | // Watch for or '?' 11 | var keyboard_is_enabled = false; 12 | $(window).keypress(function(e) { 13 | if (e.keyCode == 27) { // 14 | $(window).trigger('close'); 15 | $(document.activeElement).blur(); 16 | } 17 | if (e.which == 63 && 18 | !keyboard_is_enabled && 19 | !$(e.target).is('input, textarea, select')) { // ? 20 | var msg = 'Keyboard shortcuts are disabled. '; 21 | msg += 'Do you want to enable them?'; 22 | var enable = confirm(msg); 23 | if (enable) { 24 | _.storage.save('settings_keyboard', true); 25 | settings.keyboard = true; 26 | initKB(); 27 | $('#shortcuts').show(); 28 | } 29 | } 30 | }); 31 | 32 | function initKB() { 33 | var $shortcuts = $('
', {'class': 'shortcuts quickmodal', 34 | 'id': 'shortcuts'}).hide(), 35 | $shortcuts_table = $(''), 36 | kbCallback = {}; 37 | 38 | keyboard_is_enabled = true; 39 | 40 | $shortcuts.append($shortcuts_table); 41 | 42 | function addTitle(title) { 43 | var $tr = $(''); 44 | var $th1 = $('
'); 45 | var $th2 = $('', {'text': title}); 46 | 47 | $tr.append($th1).append($th2); 48 | 49 | $shortcuts_table.append($tr); 50 | } 51 | 52 | function newTable() { 53 | $shortcuts_table = $(''); 54 | $shortcuts.append($shortcuts_table); 55 | } 56 | 57 | function addShortcut(key, title, callback) { 58 | /* Make it do something */ 59 | var keycode = ''; 60 | for (var i = 0; i < key.length; i++) { 61 | keycode += key.charCodeAt(i) + '_'; 62 | } 63 | 64 | if (key == '+') { 65 | keycode = '13_'; 66 | key = '<enter>'; 67 | } 68 | 69 | keycode = keycode.slice(0, -1); 70 | 71 | if (typeof callback == 'string') { 72 | var url = callback; 73 | callback = function() { unsafeWindow.location = url; }; 74 | } 75 | 76 | kbCallback[keycode] = function() { 77 | if (key != '?') { 78 | $shortcuts.hide(); 79 | } 80 | callback(); 81 | }; 82 | 83 | /* Add to menu */ 84 | var $tr = $(''), 85 | $td1 = $('
', {'class': 'left'}), 86 | $td2 = $('', {'text': title}); 87 | 88 | if (key[0] == 'g') { 89 | $td1.append($('', {'html': key[0]})); 90 | $td1.append($('', {'text': 'then'})); 91 | $td1.append($('', {'html': key[1]})); 92 | } else { 93 | $td1.append($('', {'html': key})); 94 | } 95 | 96 | $td1.append($('', {'text': ':'})); 97 | 98 | $shortcuts_table.append($tr); 99 | $tr.append($td1); 100 | $tr.append($td2); 101 | } 102 | 103 | $(window).bind('close', function() { 104 | $('.quickmodal').hide(); 105 | }); 106 | 107 | var last_g = ''; 108 | $(unsafeWindow).keypress(function(e) { 109 | if ($(e.target).is('input, textarea, select') || 110 | e.ctrlKey || 111 | e.metaKey || 112 | e.altKey) { 113 | return; 114 | } 115 | 116 | var keycode = last_g + e.which; 117 | 118 | if (keycode in kbCallback) { 119 | e.preventDefault(); 120 | kbCallback[keycode](); 121 | } 122 | last_g = e.which == 103 ? '103_' : ''; 123 | }); 124 | 125 | // Some fields auto-focus, which ruins this. 126 | $(document.activeElement).blur(); 127 | 128 | $('body').append($shortcuts); 129 | 130 | function getNav(text) { 131 | return function() { 132 | $('.navigation:first a').each(function() { 133 | var $a = $(this); 134 | if ($a.text() == text) { 135 | window.location.href = $a.attr('href'); 136 | } 137 | }); 138 | }; 139 | } 140 | 141 | var $elements = []; 142 | 143 | if ($('.bz_buglist').length) { 144 | $elements = $('.sorttable_body tr'); 145 | } 146 | 147 | var el_count = $elements.length, 148 | el_current = 0; 149 | 150 | if (el_count) { 151 | $elements.eq(0).addClass('is-selected'); 152 | } 153 | 154 | function updateSelected(diff) { 155 | if (!el_count) { 156 | return; 157 | } 158 | el_current += diff; 159 | 160 | if (el_current >= el_count) { 161 | el_current = 0; 162 | } 163 | if (el_current < 0) { 164 | el_current = el_count - 1; 165 | } 166 | 167 | $elements.filter('.is-selected').removeClass('is-selected'); 168 | 169 | var $selected = $elements.eq(el_current); 170 | $selected.addClass('is-selected'); 171 | 172 | // Scroll it into view 173 | var el_position = $selected.position().top; 174 | 175 | var visible_top = $(window).scrollTop(), 176 | visible_bottom = visible_top + $(window).height(); 177 | 178 | if ($selected.length && 179 | (el_position < visible_top || el_position > visible_bottom)) { 180 | $selected[0].scrollIntoView(); 181 | } 182 | } 183 | 184 | /* ====================== 185 | * Shortcuts 186 | * ====================== */ 187 | 188 | addTitle('Global Shortcuts'); 189 | 190 | addShortcut('?', 'View shortcuts', function() { 191 | $('#shortcuts').toggle(); 192 | }); 193 | 194 | addShortcut('n', 'Quick file a new bug', function() { 195 | $(window).trigger('close'); 196 | var $fileit = $('
', {'class': 'quickmodal', 197 | 'id': 'fileit_quick'}).appendTo('body'); 198 | $fileit.fileit(); 199 | 200 | var msg = 'To close, hit <esc> · '; 201 | msg += 'To browse components, use shortcut "gn"'; 202 | $fileit.append($('
', {'class': 'light', 203 | 'html': msg})); 204 | 205 | $fileit.find('input').focus(); 206 | }); 207 | 208 | addShortcut('s', 'Search', function() { 209 | var qs = $('#quicksearch_main'); 210 | if (!qs.length) { 211 | qs = $('#quicksearch_top'); 212 | } 213 | qs.removeClass('quicksearch_help_text').val('').focus(); 214 | }); 215 | 216 | addTitle('Site Navigation'); 217 | 218 | addShortcut('gh', 'Go Home', './'); 219 | 220 | addShortcut('gn', 'Go to new bug page', './enter_bug.cgi'); 221 | 222 | addShortcut('gb', 'Go to bug #___', function() { 223 | var bug = prompt('What is the bug number?'); 224 | if (bug) { 225 | unsafeWindow.location = './show_bug.cgi?id=' + bug; 226 | } 227 | }); 228 | 229 | addShortcut('gs', 'Go to advanced search', './query.cgi?format=advanced'); 230 | 231 | addShortcut('gp', 'Go to preferences', './userprefs.cgi'); 232 | 233 | //addShortcut('g,', 'Go to BugzillaJS prefs', openPrefs); 234 | 235 | newTable(); 236 | 237 | addTitle('Bug Shortcuts'); 238 | 239 | addShortcut('r', 'Reply to bug', function() { 240 | $('#comment').focus(); 241 | }); 242 | 243 | addShortcut('J', 'Next bug in list', getNav('Next')); 244 | 245 | addShortcut('K', 'Previous bug in list', getNav('Prev')); 246 | 247 | addShortcut('H', 'First bug in list', getNav('First')); 248 | 249 | addShortcut('L', 'Last bug in list', getNav('Last')); 250 | 251 | addShortcut('gl', 'Go back to list of results', 252 | getNav('Show last search results')); 253 | 254 | addTitle('List Navigation'); 255 | 256 | addShortcut('j', 'Next entry', function() { 257 | updateSelected(1); 258 | }); 259 | 260 | addShortcut('k', 'Previous entry', function() { 261 | updateSelected(-1); 262 | }); 263 | 264 | addShortcut('+', 'Go to selected row', function() { 265 | if (el_count) { 266 | window.location.href = $elements.filter('.is-selected').find('a'). 267 | eq(0).attr('href'); 268 | } 269 | }); 270 | } 271 | -------------------------------------------------------------------------------- /js/md5.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 3 | * Digest Algorithm, as defined in RFC 1321. 4 | * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 6 | * Distributed under the BSD License 7 | * See http://pajhome.org.uk/crypt/md5 for more info. 8 | */ 9 | 10 | /* 11 | * Configurable variables. You may need to tweak these to be compatible with 12 | * the server-side, but the defaults work in most cases. 13 | */ 14 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ 15 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ 16 | 17 | /* 18 | * These are the functions you'll usually want to call 19 | * They take string arguments and return either hex or base-64 encoded strings 20 | */ 21 | function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); } 22 | function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); } 23 | function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); } 24 | function hex_hmac_md5(k, d) 25 | { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } 26 | function b64_hmac_md5(k, d) 27 | { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } 28 | function any_hmac_md5(k, d, e) 29 | { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } 30 | 31 | /* 32 | * Perform a simple self-test to see if the VM is working 33 | */ 34 | function md5_vm_test() 35 | { 36 | return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72"; 37 | } 38 | 39 | /* 40 | * Calculate the MD5 of a raw string 41 | */ 42 | function rstr_md5(s) 43 | { 44 | return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); 45 | } 46 | 47 | /* 48 | * Calculate the HMAC-MD5, of a key and some data (raw strings) 49 | */ 50 | function rstr_hmac_md5(key, data) 51 | { 52 | var bkey = rstr2binl(key); 53 | if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); 54 | 55 | var ipad = Array(16), opad = Array(16); 56 | for(var i = 0; i < 16; i++) 57 | { 58 | ipad[i] = bkey[i] ^ 0x36363636; 59 | opad[i] = bkey[i] ^ 0x5C5C5C5C; 60 | } 61 | 62 | var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); 63 | return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); 64 | } 65 | 66 | /* 67 | * Convert a raw string to a hex string 68 | */ 69 | function rstr2hex(input) 70 | { 71 | try { hexcase } catch(e) { hexcase=0; } 72 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 73 | var output = ""; 74 | var x; 75 | for(var i = 0; i < input.length; i++) 76 | { 77 | x = input.charCodeAt(i); 78 | output += hex_tab.charAt((x >>> 4) & 0x0F) 79 | + hex_tab.charAt( x & 0x0F); 80 | } 81 | return output; 82 | } 83 | 84 | /* 85 | * Convert a raw string to a base-64 string 86 | */ 87 | function rstr2b64(input) 88 | { 89 | try { b64pad } catch(e) { b64pad=''; } 90 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 91 | var output = ""; 92 | var len = input.length; 93 | for(var i = 0; i < len; i += 3) 94 | { 95 | var triplet = (input.charCodeAt(i) << 16) 96 | | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) 97 | | (i + 2 < len ? input.charCodeAt(i+2) : 0); 98 | for(var j = 0; j < 4; j++) 99 | { 100 | if(i * 8 + j * 6 > input.length * 8) output += b64pad; 101 | else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); 102 | } 103 | } 104 | return output; 105 | } 106 | 107 | /* 108 | * Convert a raw string to an arbitrary string encoding 109 | */ 110 | function rstr2any(input, encoding) 111 | { 112 | var divisor = encoding.length; 113 | var i, j, q, x, quotient; 114 | 115 | /* Convert to an array of 16-bit big-endian values, forming the dividend */ 116 | var dividend = Array(Math.ceil(input.length / 2)); 117 | for(i = 0; i < dividend.length; i++) 118 | { 119 | dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); 120 | } 121 | 122 | /* 123 | * Repeatedly perform a long division. The binary array forms the dividend, 124 | * the length of the encoding is the divisor. Once computed, the quotient 125 | * forms the dividend for the next step. All remainders are stored for later 126 | * use. 127 | */ 128 | var full_length = Math.ceil(input.length * 8 / 129 | (Math.log(encoding.length) / Math.log(2))); 130 | var remainders = Array(full_length); 131 | for(j = 0; j < full_length; j++) 132 | { 133 | quotient = Array(); 134 | x = 0; 135 | for(i = 0; i < dividend.length; i++) 136 | { 137 | x = (x << 16) + dividend[i]; 138 | q = Math.floor(x / divisor); 139 | x -= q * divisor; 140 | if(quotient.length > 0 || q > 0) 141 | quotient[quotient.length] = q; 142 | } 143 | remainders[j] = x; 144 | dividend = quotient; 145 | } 146 | 147 | /* Convert the remainders to the output string */ 148 | var output = ""; 149 | for(i = remainders.length - 1; i >= 0; i--) 150 | output += encoding.charAt(remainders[i]); 151 | 152 | return output; 153 | } 154 | 155 | /* 156 | * Encode a string as utf-8. 157 | * For efficiency, this assumes the input is valid utf-16. 158 | */ 159 | function str2rstr_utf8(input) 160 | { 161 | var output = ""; 162 | var i = -1; 163 | var x, y; 164 | 165 | while(++i < input.length) 166 | { 167 | /* Decode utf-16 surrogate pairs */ 168 | x = input.charCodeAt(i); 169 | y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; 170 | if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) 171 | { 172 | x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); 173 | i++; 174 | } 175 | 176 | /* Encode output as utf-8 */ 177 | if(x <= 0x7F) 178 | output += String.fromCharCode(x); 179 | else if(x <= 0x7FF) 180 | output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), 181 | 0x80 | ( x & 0x3F)); 182 | else if(x <= 0xFFFF) 183 | output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 184 | 0x80 | ((x >>> 6 ) & 0x3F), 185 | 0x80 | ( x & 0x3F)); 186 | else if(x <= 0x1FFFFF) 187 | output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 188 | 0x80 | ((x >>> 12) & 0x3F), 189 | 0x80 | ((x >>> 6 ) & 0x3F), 190 | 0x80 | ( x & 0x3F)); 191 | } 192 | return output; 193 | } 194 | 195 | /* 196 | * Encode a string as utf-16 197 | */ 198 | function str2rstr_utf16le(input) 199 | { 200 | var output = ""; 201 | for(var i = 0; i < input.length; i++) 202 | output += String.fromCharCode( input.charCodeAt(i) & 0xFF, 203 | (input.charCodeAt(i) >>> 8) & 0xFF); 204 | return output; 205 | } 206 | 207 | function str2rstr_utf16be(input) 208 | { 209 | var output = ""; 210 | for(var i = 0; i < input.length; i++) 211 | output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, 212 | input.charCodeAt(i) & 0xFF); 213 | return output; 214 | } 215 | 216 | /* 217 | * Convert a raw string to an array of little-endian words 218 | * Characters >255 have their high-byte silently ignored. 219 | */ 220 | function rstr2binl(input) 221 | { 222 | var output = Array(input.length >> 2); 223 | for(var i = 0; i < output.length; i++) 224 | output[i] = 0; 225 | for(var i = 0; i < input.length * 8; i += 8) 226 | output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32); 227 | return output; 228 | } 229 | 230 | /* 231 | * Convert an array of little-endian words to a string 232 | */ 233 | function binl2rstr(input) 234 | { 235 | var output = ""; 236 | for(var i = 0; i < input.length * 32; i += 8) 237 | output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF); 238 | return output; 239 | } 240 | 241 | /* 242 | * Calculate the MD5 of an array of little-endian words, and a bit length. 243 | */ 244 | function binl_md5(x, len) 245 | { 246 | /* append padding */ 247 | x[len >> 5] |= 0x80 << ((len) % 32); 248 | x[(((len + 64) >>> 9) << 4) + 14] = len; 249 | 250 | var a = 1732584193; 251 | var b = -271733879; 252 | var c = -1732584194; 253 | var d = 271733878; 254 | 255 | for(var i = 0; i < x.length; i += 16) 256 | { 257 | var olda = a; 258 | var oldb = b; 259 | var oldc = c; 260 | var oldd = d; 261 | 262 | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); 263 | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); 264 | c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); 265 | b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); 266 | a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); 267 | d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); 268 | c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); 269 | b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); 270 | a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); 271 | d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); 272 | c = md5_ff(c, d, a, b, x[i+10], 17, -42063); 273 | b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); 274 | a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); 275 | d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); 276 | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); 277 | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); 278 | 279 | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); 280 | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); 281 | c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); 282 | b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); 283 | a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); 284 | d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); 285 | c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); 286 | b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); 287 | a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); 288 | d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); 289 | c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); 290 | b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); 291 | a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); 292 | d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); 293 | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); 294 | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); 295 | 296 | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); 297 | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); 298 | c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); 299 | b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); 300 | a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); 301 | d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); 302 | c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); 303 | b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); 304 | a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); 305 | d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); 306 | c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); 307 | b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); 308 | a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); 309 | d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); 310 | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); 311 | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); 312 | 313 | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); 314 | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); 315 | c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); 316 | b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); 317 | a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); 318 | d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); 319 | c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); 320 | b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); 321 | a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); 322 | d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); 323 | c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); 324 | b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); 325 | a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); 326 | d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); 327 | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); 328 | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); 329 | 330 | a = safe_add(a, olda); 331 | b = safe_add(b, oldb); 332 | c = safe_add(c, oldc); 333 | d = safe_add(d, oldd); 334 | } 335 | return Array(a, b, c, d); 336 | } 337 | 338 | /* 339 | * These functions implement the four basic operations the algorithm uses. 340 | */ 341 | function md5_cmn(q, a, b, x, s, t) 342 | { 343 | return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); 344 | } 345 | function md5_ff(a, b, c, d, x, s, t) 346 | { 347 | return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); 348 | } 349 | function md5_gg(a, b, c, d, x, s, t) 350 | { 351 | return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); 352 | } 353 | function md5_hh(a, b, c, d, x, s, t) 354 | { 355 | return md5_cmn(b ^ c ^ d, a, b, x, s, t); 356 | } 357 | function md5_ii(a, b, c, d, x, s, t) 358 | { 359 | return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); 360 | } 361 | 362 | /* 363 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally 364 | * to work around bugs in some JS interpreters. 365 | */ 366 | function safe_add(x, y) 367 | { 368 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); 369 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); 370 | return (msw << 16) | (lsw & 0xFFFF); 371 | } 372 | 373 | /* 374 | * Bitwise rotate a 32-bit number to the left. 375 | */ 376 | function bit_rol(num, cnt) 377 | { 378 | return (num << cnt) | (num >>> (32 - cnt)); 379 | } -------------------------------------------------------------------------------- /css/bugzillajs.css: -------------------------------------------------------------------------------- 1 | span.assignee { 2 | padding-left: 10px; 3 | color: #E41313; 4 | } 5 | 6 | span.reporter { 7 | padding-left: 10px; 8 | color: #888; 9 | } 10 | 11 | /** Hide CSS? **/ 12 | .setting-hide-cc .hide-cc { 13 | display: none; 14 | } 15 | 16 | /** Style comments **/ 17 | 18 | 19 | .git_style .bz_comment { 20 | -moz-border-radius:2px 2px 2px 2px; 21 | background-color:#EEEEEE; 22 | border:1px solid #CCCCCC; 23 | padding:3px; 24 | margin-left:15px; 25 | margin-bottom:1em; 26 | width: 677px; 27 | } 28 | 29 | .bz_first_comment_head, .bz_comment_head { 30 | margin-left:0px; 31 | } 32 | 33 | .git_style .bz_first_comment, 34 | .git_style .no-first-comment .bz_comment { 35 | margin-left:0; 36 | width: 692px; 37 | } 38 | 39 | .git_style .bz_first_comment_head, 40 | .git_style .bz_comment_head { 41 | border:1px solid #CCCCCC; 42 | font-size:11px; 43 | overflow:auto; 44 | padding:5px; 45 | background: -moz-linear-gradient( 46 | center top, 47 | rgb(241,247,248) 28%, 48 | rgb(221,233,236) 64% 49 | ) repeat scroll 0% 0% transparent; 50 | } 51 | 52 | .git_style .bz_first_comment_head, 53 | .git_style .bz_reporter .bz_comment_head { 54 | background: -moz-linear-gradient( 55 | center top, 56 | #E6F4EC 28%, 57 | #D8E6DE 64% 58 | ) repeat scroll 0% 0% transparent; 59 | } 60 | 61 | .git_style .bz_comment_actions, .git_style .bz_comment_number { 62 | color:#999; 63 | padding-top:7px; 64 | } 65 | 66 | .git_style .bz_comment_actions a, .git_style .bz_comment_number a { 67 | color:#666; 68 | text-decoration:none; 69 | } 70 | 71 | .git_style .bz_comment_actions a:hover, .git_style .bz_comment_number a:hover { 72 | color:#444; 73 | text-decoration:underline; 74 | } 75 | 76 | .git_style .bz_comment_text { 77 | background-color:#FFFFFF; 78 | border-left:1px solid #CCCCCC; 79 | border-right:1px solid #CCCCCC; 80 | border-bottom:1px solid #CCCCCC; 81 | margin:0; 82 | padding:10px; 83 | } 84 | 85 | .git_style .bz_comment_user { 86 | display: inline-block; padding-top: 7px; 87 | 88 | } 89 | 90 | body:not(.skin-Mozilla).git_style .bz_comment_user a.email { 91 | text-decoration:none; 92 | color:#333; 93 | font-weight:bold; 94 | } 95 | 96 | .git_style .bz_comment_time { 97 | color:#999; 98 | font-weight: normal; 99 | } 100 | 101 | /** Inline changes **/ 102 | .git_style .ih_history .bz_comment_head { 103 | background: none repeat scroll 0% 0% transparent; 104 | border: 0pt none; 105 | display: inline; 106 | padding: 0; 107 | } 108 | 109 | .git_style .bz_comment.ih_history { 110 | font-size: 11px; 111 | padding: 5px 5px 0 5px; 112 | } 113 | 114 | .git_style .bz_comment.ih_history .ih_history_item { 115 | margin-bottom: 5px; 116 | overflow: hidden; 117 | } 118 | 119 | .git_style .bz_comment.ih_history .bz_comment_user { 120 | padding-top: 0; 121 | } 122 | 123 | .git_style .bz_comment .ih_inlinehistory { 124 | background-color: #F7F7F7; 125 | border-color: -moz-use-text-color #CCCCCC #CCCCCC; 126 | border-style: none solid solid; 127 | border-width: 0 1px 1px; 128 | font-size: 11px; 129 | padding: 3px; 130 | } 131 | 132 | /** Gravatar **/ 133 | 134 | 135 | .git_style .bz_comment_head img.gravatar, 136 | .git_style .bz_first_comment_head img.gravatar { 137 | background-color:#FFFFFF; 138 | border:1px solid #BBBBBB; 139 | padding:2px; 140 | margin-right:5px; 141 | } 142 | 143 | 144 | .bz_comment_head img.gravatar, 145 | .bz_first_comment_head img.gravatar { 146 | height:25px; 147 | } 148 | 149 | .git_style .bz_comment_head img.gravatar, 150 | .git_style .bz_first_comment_head img.gravatar { 151 | float:left; 152 | } 153 | 154 | /** Comment Overflow **/ 155 | 156 | .bzJS-commentoverflow .bz_comment pre { 157 | overflow-x: auto; 158 | } 159 | 160 | /** Remove Access Keys **/ 161 | 162 | .bzJS-removeaccesskeys .accessKey u { 163 | text-decoration: none; 164 | } 165 | 166 | /** Image gallery **/ 167 | 168 | .img-gal{ 169 | overflow:auto; 170 | width:100%; 171 | } 172 | 173 | .git_style .img-gal{ 174 | border-left:1px solid #ccc; 175 | border-right:1px solid #ccc; 176 | border-bottom:1px solid #ccc; 177 | overflow:auto; 178 | padding:20px 0 0 20px; 179 | background-color:#F1F7F8; 180 | width:655px; 181 | } 182 | 183 | .git_style .bz_first_comment .img-gal { 184 | background-color:#F3FAF6; 185 | width:670px; 186 | } 187 | 188 | .img-gal a { 189 | position: relative; 190 | width: 100px; 191 | height: 100px; 192 | padding: 4px; 193 | float: left; 194 | margin:0 20px 20px 0; 195 | border:1px solid #ddd; 196 | background-color: #fff; 197 | } 198 | 199 | .img-gal a:hover { 200 | border: 1px solid #ccc; 201 | } 202 | 203 | .img-gal a img { 204 | position: absolute; 205 | margin: auto; 206 | max-height: 100px; 207 | max-width: 100px; 208 | top: 0; 209 | right: 0; 210 | left: 0; 211 | bottom: 0; 212 | } 213 | 214 | 215 | /* Changes */ 216 | 217 | .git_style .changes { 218 | color:#555555; 219 | margin-left:20px; 220 | padding-top:10px; 221 | } 222 | 223 | .git_style .changes th { 224 | border-bottom:1px solid #DDDDDD; 225 | color:#666666; 226 | padding:0 30px 0 10px; 227 | font-size:11px; 228 | text-align:left; 229 | } 230 | 231 | .git_style .changes td { 232 | font-size:11px; 233 | padding:0 30px 0 10px; 234 | } 235 | 236 | .history { 237 | background-color:#F3F3F3; 238 | border-bottom:1px solid #DDDDDD; 239 | border-top:2px solid #DDDDDD; 240 | font-size:12px; 241 | margin-bottom:10px; 242 | padding:5px; 243 | } 244 | 245 | .bz_comment .history { 246 | background-color: transparent; 247 | border: medium none; 248 | color: #888888; 249 | margin-bottom: 0; 250 | padding: 10px 0 0; 251 | } 252 | 253 | .git_style .history { 254 | -moz-border-radius:3px 3px 3px 3px; 255 | background-color:#EEEEEE; 256 | border:1px solid #DDDDDD; 257 | color:#555555; 258 | font-size:10px; 259 | margin:0 0 1em 15px; 260 | padding:5px 10px; 261 | width:663px; 262 | font-family:verdana; 263 | } 264 | 265 | .git_style .bz_comment .history { 266 | padding:0 0 10px 0; 267 | color:#888; 268 | border:none; 269 | background-color:#fff; 270 | margin:0; 271 | border-left: 1px solid #CCCCCC; 272 | -moz-border-radius: 0; 273 | -webkit-border-radius: 0; 274 | border-radius: 0; 275 | border-right: 1px solid #CCCCCC; 276 | padding: 6px; 277 | width: auto; 278 | } 279 | 280 | .git_style #attachment_table { 281 | width:700px; 282 | } 283 | 284 | 285 | 286 | /** Git stuff **/ 287 | 288 | .git_style .git-body { 289 | background-color:#F9F9F9; 290 | border-bottom:1px solid #CCCCCC; 291 | border-left:1px solid #CCCCCC; 292 | border-right:1px solid #CCCCCC; 293 | padding:10px; 294 | width:auto; 295 | } 296 | 297 | .git-head { 298 | background-color:#EAF2F5; 299 | border:1px solid #BEDCE7; 300 | padding:10px; 301 | } 302 | 303 | .git-head p { 304 | margin-top:0; 305 | } 306 | 307 | .git-head span { 308 | font-size:11px; 309 | color:#888; 310 | } 311 | 312 | .git-head span strong { 313 | color:#666; 314 | } 315 | 316 | .git tr { 317 | border-top:1px solid #ddd; 318 | } 319 | .git { 320 | background-color:#FFFFFF; 321 | border-bottom:1px solid #DDDDDD; 322 | border-collapse:collapse; 323 | margin:10px 0 0; 324 | width:100%; 325 | } 326 | 327 | .git .changes_box { 328 | position:relative; 329 | } 330 | 331 | .git td .changes_box div { 332 | display:none; 333 | } 334 | 335 | .git td:hover .changes_box div { 336 | -webkit-border-radius:4px; 337 | -moz-border-radius:4px; 338 | background-color:black; 339 | color:#FFFFFF; 340 | font-size:10px; 341 | left:-165px; 342 | opacity:0.8; 343 | padding:2px 3px; 344 | position:absolute; 345 | text-align:center; 346 | top:0; 347 | width:150px; 348 | display:block; 349 | } 350 | 351 | .git .changes_box strong { 352 | color:#444444; 353 | display:block; 354 | float:left; 355 | padding-right:5px; 356 | padding-top:1px; 357 | text-align:right; 358 | width:25px; 359 | 360 | } 361 | 362 | .git td.changes_td { 363 | width:80px; 364 | } 365 | 366 | .git td { 367 | padding:5px; 368 | font-size:11px; 369 | } 370 | 371 | 372 | .git td.add .stat-icon { 373 | background-position:0 0; 374 | } 375 | 376 | .git td.modify .stat-icon { 377 | background-position:0px -50px; 378 | } 379 | 380 | .git td.remove .stat-icon { 381 | background-position:0px -100px; 382 | } 383 | 384 | .git td .stat-icon { 385 | display:block; 386 | height:19px; 387 | text-indent:-9999px; 388 | width:20px; 389 | } 390 | 391 | .gb, .ga, .gd { 392 | -moz-border-radius:2px 2px 2px 2px; 393 | background-color:#DDD; 394 | float:left; 395 | height:8px; 396 | margin-right:2px; 397 | margin-top:5px; 398 | width:8px; 399 | } 400 | 401 | .ga { 402 | background-color:#61C423 403 | } 404 | .gd { 405 | background-color:#C52323 406 | } 407 | 408 | 409 | /* Lightbox */ 410 | 411 | 412 | .lb { 413 | background-color: #FFFFFF; 414 | border: 1px solid #666666; 415 | box-shadow: 0 0 10px #555555; 416 | -moz-box-shadow: 0 0 10px #555555; 417 | padding: 10px; 418 | max-width: 90%; 419 | -moz-box-sizing: border-box; 420 | margin: 20px auto; 421 | } 422 | 423 | .overlay2 { 424 | position: absolute; 425 | left: 0; 426 | width: 100%; 427 | text-align: center; 428 | z-index: 2; 429 | } 430 | 431 | .overlay { 432 | background:none repeat scroll 0 0 rgba(0, 0, 0, 0.5); 433 | height:100%; 434 | left:0; 435 | position:fixed; 436 | text-align:center; 437 | top:0; 438 | width:100%; 439 | z-index: 2; 440 | } 441 | 442 | .opts { 443 | color: #FFFFFF; 444 | font-size: 10px; 445 | font-weight: bold; 446 | left: 0; 447 | padding: 5px; 448 | position: fixed; 449 | text-shadow: 1px 1px 1px #000000; 450 | top: 0; 451 | z-index: 1000; 452 | } 453 | 454 | .opts a { 455 | text-decoration:none; 456 | color:#fff; 457 | } 458 | 459 | .lb, .overlay { 460 | -moz-transition: opacity 0.3s ease; 461 | } 462 | 463 | 464 | .quickmodal { 465 | background-color: rgba(0, 0, 0, 0.8); 466 | border-radius: 5px; 467 | color: #FFFFFF; 468 | left: 50%; 469 | margin-left: -315px; 470 | margin-top: 100px; 471 | padding: 15px; 472 | position: fixed; 473 | top: 0; 474 | width: 600px; 475 | } 476 | 477 | .shortcuts tr:first-child th { 478 | padding-top: 0; 479 | } 480 | .shortcuts th { 481 | padding-top: 20px; 482 | text-align: left; 483 | color: #8895B7; 484 | border-bottom: 1px dotted #888; 485 | padding-bottom: 3px; 486 | } 487 | 488 | .shortcuts table { 489 | float: left; 490 | border-collapse: collapse; 491 | margin: 10px; 492 | width: 280px; 493 | } 494 | 495 | .shortcuts .left { 496 | text-align: right; 497 | padding-right: 5px; 498 | min-width: 70px; 499 | } 500 | 501 | .shortcuts .left strong { 502 | color: #8895B7; 503 | font-weight: bold; 504 | } 505 | 506 | .shortcuts .left em { 507 | font-size: 0.7em; 508 | font-style: normal; 509 | font-weight: bold; 510 | padding: 0 5px; 511 | text-transform: uppercase; 512 | } 513 | 514 | .notify { 515 | background-color: #990505; 516 | border-radius: 5px 5px 5px 5px; 517 | color: #FFFFFF; 518 | margin-left: 10px; 519 | padding: 2px 5px; 520 | position: relative; 521 | } 522 | 523 | .notify:before { 524 | border: 5px solid transparent; 525 | border-color: transparent #990505 transparent transparent; 526 | content: " "; 527 | height: 0; 528 | left: -9px; 529 | margin-top: -6px; 530 | position: absolute; 531 | top: 50%; 532 | width: 0; 533 | } 534 | 535 | .show_new { 536 | color: red; 537 | font-size: 0.8em; 538 | font-weight: bold; 539 | padding-right: 5px; 540 | text-transform: uppercase; 541 | } 542 | 543 | #bugzilla-body .fileit { 544 | width: 600px; 545 | margin: auto; 546 | margin-bottom: 1em; 547 | border-bottom: 1px dotted #ccc; 548 | padding: 1em 0; 549 | } 550 | 551 | #fileit_quick .light { 552 | padding-top: 10px; 553 | font-size: 0.8em; 554 | color: #CCC; 555 | text-align: center; 556 | } 557 | 558 | .fileit { 559 | text-align: center; 560 | position: relative; 561 | } 562 | 563 | .fileit input { 564 | width: 350px; 565 | border: 1px solid #AAAAAA; 566 | margin: 0 10px; 567 | padding: 5px; 568 | font-size: 13px; 569 | } 570 | 571 | .fileit button { 572 | background-color: #DDDDDD; 573 | border: 1px solid #AAA; 574 | color: #555555; 575 | font-weight: bold; 576 | padding: 4px 10px; 577 | text-shadow: 1px 1px #FFFFFF; 578 | font-size: 13px; 579 | } 580 | 581 | .fileit ul { 582 | position: absolute; 583 | background-color: #fff; 584 | margin: 0; 585 | padding: 0; 586 | list-style: none; 587 | border: 1px solid #999999; 588 | border-top: 0 none; 589 | -moz-box-sizing: border-box; 590 | box-sizing: border-box; 591 | } 592 | 593 | .fileit ul li { 594 | padding: 5px; 595 | font-size: 0.85em; 596 | text-align: left; 597 | cursor: pointer; 598 | } 599 | 600 | .fileit ul li:hover { 601 | background-color: #ddd !important; 602 | } 603 | 604 | .fileit ul li.active { 605 | background-color: #eee; 606 | } 607 | .fileit ul li span { 608 | color: #888; 609 | font-size: 0.9em; 610 | width: 120px; 611 | display: inline-block; 612 | } 613 | 614 | .fileit ul li strong { 615 | font-weight: normal; 616 | color: #000; 617 | } 618 | 619 | /* Arrow for up/down keyboard shortcuts */ 620 | .sorttable_body tr.is-selected .first-child a { 621 | position: relative; 622 | } 623 | .sorttable_body tr.is-selected .first-child a:before { 624 | border-color: transparent transparent transparent #666666; 625 | border-style: solid; 626 | border-width: 5px; 627 | content: " "; 628 | display: block; 629 | height: 0; 630 | left: -11px; 631 | position: absolute; 632 | top: 5px; 633 | width: 0; 634 | } 635 | 636 | .treeherder_inline_result { 637 | width: 100%; 638 | border: 1px solid #ddd; 639 | background-color: white; 640 | height: 60px; 641 | } 642 | 643 | .iframe_focused { 644 | height: 600px; 645 | } 646 | -------------------------------------------------------------------------------- /legacy/jquery.flot.pie.js: -------------------------------------------------------------------------------- 1 | /* 2 | Flot plugin for rendering pie charts. The plugin assumes the data is 3 | coming is as a single data value for each series, and each of those 4 | values is a positive value or zero (negative numbers don't make 5 | any sense and will cause strange effects). The data values do 6 | NOT need to be passed in as percentage values because it 7 | internally calculates the total and percentages. 8 | 9 | * Created by Brian Medendorp, June 2009 10 | * Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars 11 | 12 | * Changes: 13 | 2009-10-22: lineJoin set to round 14 | 2009-10-23: IE full circle fix, donut 15 | 2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera 16 | 2009-11-17: Added IE hover capability submitted by Anthony Aragues 17 | 2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well) 18 | 19 | 20 | Available options are: 21 | series: { 22 | pie: { 23 | show: true/false 24 | radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto' 25 | innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect 26 | startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result 27 | tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show) 28 | offset: { 29 | top: integer value to move the pie up or down 30 | left: integer value to move the pie left or right, or 'auto' 31 | }, 32 | stroke: { 33 | color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF') 34 | width: integer pixel width of the stroke 35 | }, 36 | label: { 37 | show: true/false, or 'auto' 38 | formatter: a user-defined function that modifies the text/style of the label text 39 | radius: 0-1 for percentage of fullsize, or a specified pixel length 40 | background: { 41 | color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000') 42 | opacity: 0-1 43 | }, 44 | threshold: 0-1 for the percentage value at which to hide labels (if they're too small) 45 | }, 46 | combine: { 47 | threshold: 0-1 for the percentage value at which to combine slices (if they're too small) 48 | color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined 49 | label: any text value of what the combined slice should be labeled 50 | } 51 | highlight: { 52 | opacity: 0-1 53 | } 54 | } 55 | } 56 | 57 | More detail and specific examples can be found in the included HTML file. 58 | 59 | */ 60 | 61 | (function ($) 62 | { 63 | function init(plot) // this is the "body" of the plugin 64 | { 65 | var canvas = null; 66 | var target = null; 67 | var maxRadius = null; 68 | var centerLeft = null; 69 | var centerTop = null; 70 | var total = 0; 71 | var redraw = true; 72 | var redrawAttempts = 10; 73 | var shrink = 0.95; 74 | var legendWidth = 0; 75 | var processed = false; 76 | var raw = false; 77 | 78 | // interactive variables 79 | var highlights = []; 80 | 81 | // add hook to determine if pie plugin in enabled, and then perform necessary operations 82 | plot.hooks.processOptions.push(checkPieEnabled); 83 | plot.hooks.bindEvents.push(bindEvents); 84 | 85 | // check to see if the pie plugin is enabled 86 | function checkPieEnabled(plot, options) 87 | { 88 | if (options.series.pie.show) 89 | { 90 | //disable grid 91 | options.grid.show = false; 92 | 93 | // set labels.show 94 | if (options.series.pie.label.show=='auto') 95 | if (options.legend.show) 96 | options.series.pie.label.show = false; 97 | else 98 | options.series.pie.label.show = true; 99 | 100 | // set radius 101 | if (options.series.pie.radius=='auto') 102 | if (options.series.pie.label.show) 103 | options.series.pie.radius = 3/4; 104 | else 105 | options.series.pie.radius = 1; 106 | 107 | // ensure sane tilt 108 | if (options.series.pie.tilt>1) 109 | options.series.pie.tilt=1; 110 | if (options.series.pie.tilt<0) 111 | options.series.pie.tilt=0; 112 | 113 | // add processData hook to do transformations on the data 114 | plot.hooks.processDatapoints.push(processDatapoints); 115 | plot.hooks.drawOverlay.push(drawOverlay); 116 | 117 | // add draw hook 118 | plot.hooks.draw.push(draw); 119 | } 120 | } 121 | 122 | // bind hoverable events 123 | function bindEvents(plot, eventHolder) 124 | { 125 | var options = plot.getOptions(); 126 | 127 | if (options.series.pie.show && options.grid.hoverable) 128 | eventHolder.unbind('mousemove').mousemove(onMouseMove); 129 | 130 | if (options.series.pie.show && options.grid.clickable) 131 | eventHolder.unbind('click').click(onClick); 132 | } 133 | 134 | 135 | // debugging function that prints out an object 136 | function alertObject(obj) 137 | { 138 | var msg = ''; 139 | function traverse(obj, depth) 140 | { 141 | if (!depth) 142 | depth = 0; 143 | for (var i = 0; i < obj.length; ++i) 144 | { 145 | for (var j=0; jcanvas.width-maxRadius) 207 | centerLeft = canvas.width-maxRadius; 208 | } 209 | 210 | function fixData(data) 211 | { 212 | for (var i = 0; i < data.length; ++i) 213 | { 214 | if (typeof(data[i].data)=='number') 215 | data[i].data = [[1,data[i].data]]; 216 | else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined') 217 | { 218 | if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined') 219 | data[i].label = data[i].data.label; // fix weirdness coming from flot 220 | data[i].data = [[1,0]]; 221 | 222 | } 223 | } 224 | return data; 225 | } 226 | 227 | function combine(data) 228 | { 229 | data = fixData(data); 230 | calcTotal(data); 231 | var combined = 0; 232 | var numCombined = 0; 233 | var color = options.series.pie.combine.color; 234 | 235 | var newdata = []; 236 | for (var i = 0; i < data.length; ++i) 237 | { 238 | // make sure its a number 239 | data[i].data[0][1] = parseFloat(data[i].data[0][1]); 240 | if (!data[i].data[0][1]) 241 | data[i].data[0][1] = 0; 242 | 243 | if (data[i].data[0][1]/total<=options.series.pie.combine.threshold) 244 | { 245 | combined += data[i].data[0][1]; 246 | numCombined++; 247 | if (!color) 248 | color = data[i].color; 249 | } 250 | else 251 | { 252 | newdata.push({ 253 | data: [[1,data[i].data[0][1]]], 254 | color: data[i].color, 255 | label: data[i].label, 256 | angle: (data[i].data[0][1]*(Math.PI*2))/total, 257 | percent: (data[i].data[0][1]/total*100) 258 | }); 259 | } 260 | } 261 | if (numCombined>0) 262 | newdata.push({ 263 | data: [[1,combined]], 264 | color: color, 265 | label: options.series.pie.combine.label, 266 | angle: (combined*(Math.PI*2))/total, 267 | percent: (combined/total*100) 268 | }); 269 | return newdata; 270 | } 271 | 272 | function draw(plot, newCtx) 273 | { 274 | if (!target) return; // if no series were passed 275 | ctx = newCtx; 276 | 277 | setupPie(); 278 | var slices = plot.getData(); 279 | 280 | var attempts = 0; 281 | while (redraw && attempts0) 285 | maxRadius *= shrink; 286 | attempts += 1; 287 | clear(); 288 | if (options.series.pie.tilt<=0.8) 289 | drawShadow(); 290 | drawPie(); 291 | } 292 | if (attempts >= redrawAttempts) { 293 | clear(); 294 | target.prepend('
Could not draw pie with labels contained inside canvas
'); 295 | } 296 | 297 | if ( plot.setSeries && plot.insertLegend ) 298 | { 299 | plot.setSeries(slices); 300 | plot.insertLegend(); 301 | } 302 | 303 | // we're actually done at this point, just defining internal functions at this point 304 | 305 | function clear() 306 | { 307 | ctx.clearRect(0,0,canvas.width,canvas.height); 308 | target.children().filter('.pieLabel, .pieLabelBackground').remove(); 309 | } 310 | 311 | function drawShadow() 312 | { 313 | var shadowLeft = 5; 314 | var shadowTop = 15; 315 | var edge = 10; 316 | var alpha = 0.02; 317 | 318 | // set radius 319 | if (options.series.pie.radius>1) 320 | var radius = options.series.pie.radius; 321 | else 322 | var radius = maxRadius * options.series.pie.radius; 323 | 324 | if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge) 325 | return; // shadow would be outside canvas, so don't draw it 326 | 327 | ctx.save(); 328 | ctx.translate(shadowLeft,shadowTop); 329 | ctx.globalAlpha = alpha; 330 | ctx.fillStyle = '#000'; 331 | 332 | // center and rotate to starting position 333 | ctx.translate(centerLeft,centerTop); 334 | ctx.scale(1, options.series.pie.tilt); 335 | 336 | //radius -= edge; 337 | for (var i=1; i<=edge; i++) 338 | { 339 | ctx.beginPath(); 340 | ctx.arc(0,0,radius,0,Math.PI*2,false); 341 | ctx.fill(); 342 | radius -= i; 343 | } 344 | 345 | ctx.restore(); 346 | } 347 | 348 | function drawPie() 349 | { 350 | startAngle = Math.PI*options.series.pie.startAngle; 351 | 352 | // set radius 353 | if (options.series.pie.radius>1) 354 | var radius = options.series.pie.radius; 355 | else 356 | var radius = maxRadius * options.series.pie.radius; 357 | 358 | // center and rotate to starting position 359 | ctx.save(); 360 | ctx.translate(centerLeft,centerTop); 361 | ctx.scale(1, options.series.pie.tilt); 362 | //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera 363 | 364 | // draw slices 365 | ctx.save(); 366 | var currentAngle = startAngle; 367 | for (var i = 0; i < slices.length; ++i) 368 | { 369 | slices[i].startAngle = currentAngle; 370 | drawSlice(slices[i].angle, slices[i].color, true); 371 | } 372 | ctx.restore(); 373 | 374 | // draw slice outlines 375 | ctx.save(); 376 | ctx.lineWidth = options.series.pie.stroke.width; 377 | currentAngle = startAngle; 378 | for (var i = 0; i < slices.length; ++i) 379 | drawSlice(slices[i].angle, options.series.pie.stroke.color, false); 380 | ctx.restore(); 381 | 382 | // draw donut hole 383 | drawDonutHole(ctx); 384 | 385 | // draw labels 386 | if (options.series.pie.label.show) 387 | drawLabels(); 388 | 389 | // restore to original state 390 | ctx.restore(); 391 | 392 | function drawSlice(angle, color, fill) 393 | { 394 | if (angle<=0) 395 | return; 396 | 397 | if (fill) 398 | ctx.fillStyle = color; 399 | else 400 | { 401 | ctx.strokeStyle = color; 402 | ctx.lineJoin = 'round'; 403 | } 404 | 405 | ctx.beginPath(); 406 | if (Math.abs(angle - Math.PI*2) > 0.000000001) 407 | ctx.moveTo(0,0); // Center of the pie 408 | else if ($.browser.msie) 409 | angle -= 0.0001; 410 | //ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera 411 | ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false); 412 | ctx.closePath(); 413 | //ctx.rotate(angle); // This doesn't work properly in Opera 414 | currentAngle += angle; 415 | 416 | if (fill) 417 | ctx.fill(); 418 | else 419 | ctx.stroke(); 420 | } 421 | 422 | function drawLabels() 423 | { 424 | var currentAngle = startAngle; 425 | 426 | // set radius 427 | if (options.series.pie.label.radius>1) 428 | var radius = options.series.pie.label.radius; 429 | else 430 | var radius = maxRadius * options.series.pie.label.radius; 431 | 432 | for (var i = 0; i < slices.length; ++i) 433 | { 434 | if (slices[i].percent >= options.series.pie.label.threshold*100) 435 | drawLabel(slices[i], currentAngle, i); 436 | currentAngle += slices[i].angle; 437 | } 438 | 439 | function drawLabel(slice, startAngle, index) 440 | { 441 | if (slice.data[0][1]==0) 442 | return; 443 | 444 | // format label text 445 | var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter; 446 | if (lf) 447 | text = lf(slice.label, slice); 448 | else 449 | text = slice.label; 450 | if (plf) 451 | text = plf(text, slice); 452 | 453 | var halfAngle = ((startAngle+slice.angle) + startAngle)/2; 454 | var x = centerLeft + Math.round(Math.cos(halfAngle) * radius); 455 | var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt; 456 | 457 | var html = '' + text + ""; 458 | target.append(html); 459 | var label = target.children('#pieLabel'+index); 460 | var labelTop = (y - label.height()/2); 461 | var labelLeft = (x - label.width()/2); 462 | label.css('top', labelTop); 463 | label.css('left', labelLeft); 464 | 465 | // check to make sure that the label is not outside the canvas 466 | if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0) 467 | redraw = true; 468 | 469 | if (options.series.pie.label.background.opacity != 0) { 470 | // put in the transparent background separately to avoid blended labels and label boxes 471 | var c = options.series.pie.label.background.color; 472 | if (c == null) { 473 | c = slice.color; 474 | } 475 | var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;'; 476 | $('
').insertBefore(label).css('opacity', options.series.pie.label.background.opacity); 477 | } 478 | } // end individual label function 479 | } // end drawLabels function 480 | } // end drawPie function 481 | } // end draw function 482 | 483 | // Placed here because it needs to be accessed from multiple locations 484 | function drawDonutHole(layer) 485 | { 486 | // draw donut hole 487 | if(options.series.pie.innerRadius > 0) 488 | { 489 | // subtract the center 490 | layer.save(); 491 | innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius; 492 | layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color 493 | layer.beginPath(); 494 | layer.fillStyle = options.series.pie.stroke.color; 495 | layer.arc(0,0,innerRadius,0,Math.PI*2,false); 496 | layer.fill(); 497 | layer.closePath(); 498 | layer.restore(); 499 | 500 | // add inner stroke 501 | layer.save(); 502 | layer.beginPath(); 503 | layer.strokeStyle = options.series.pie.stroke.color; 504 | layer.arc(0,0,innerRadius,0,Math.PI*2,false); 505 | layer.stroke(); 506 | layer.closePath(); 507 | layer.restore(); 508 | // TODO: add extra shadow inside hole (with a mask) if the pie is tilted. 509 | } 510 | } 511 | 512 | //-- Additional Interactive related functions -- 513 | 514 | function isPointInPoly(poly, pt) 515 | { 516 | for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) 517 | ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1])) 518 | && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0]) 519 | && (c = !c); 520 | return c; 521 | } 522 | 523 | function findNearbySlice(mouseX, mouseY) 524 | { 525 | var slices = plot.getData(), 526 | options = plot.getOptions(), 527 | radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; 528 | 529 | for (var i = 0; i < slices.length; ++i) 530 | { 531 | var s = slices[i]; 532 | 533 | if(s.pie.show) 534 | { 535 | ctx.save(); 536 | ctx.beginPath(); 537 | ctx.moveTo(0,0); // Center of the pie 538 | //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here. 539 | ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false); 540 | ctx.closePath(); 541 | x = mouseX-centerLeft; 542 | y = mouseY-centerTop; 543 | if(ctx.isPointInPath) 544 | { 545 | if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop)) 546 | { 547 | //alert('found slice!'); 548 | ctx.restore(); 549 | return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i}; 550 | } 551 | } 552 | else 553 | { 554 | // excanvas for IE doesn;t support isPointInPath, this is a workaround. 555 | p1X = (radius * Math.cos(s.startAngle)); 556 | p1Y = (radius * Math.sin(s.startAngle)); 557 | p2X = (radius * Math.cos(s.startAngle+(s.angle/4))); 558 | p2Y = (radius * Math.sin(s.startAngle+(s.angle/4))); 559 | p3X = (radius * Math.cos(s.startAngle+(s.angle/2))); 560 | p3Y = (radius * Math.sin(s.startAngle+(s.angle/2))); 561 | p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5))); 562 | p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5))); 563 | p5X = (radius * Math.cos(s.startAngle+s.angle)); 564 | p5Y = (radius * Math.sin(s.startAngle+s.angle)); 565 | arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]]; 566 | arrPoint = [x,y]; 567 | // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt? 568 | if(isPointInPoly(arrPoly, arrPoint)) 569 | { 570 | ctx.restore(); 571 | return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i}; 572 | } 573 | } 574 | ctx.restore(); 575 | } 576 | } 577 | 578 | return null; 579 | } 580 | 581 | function onMouseMove(e) 582 | { 583 | triggerClickHoverEvent('plothover', e); 584 | } 585 | 586 | function onClick(e) 587 | { 588 | triggerClickHoverEvent('plotclick', e); 589 | } 590 | 591 | // trigger click or hover event (they send the same parameters so we share their code) 592 | function triggerClickHoverEvent(eventname, e) 593 | { 594 | var offset = plot.offset(), 595 | canvasX = parseInt(e.pageX - offset.left), 596 | canvasY = parseInt(e.pageY - offset.top), 597 | item = findNearbySlice(canvasX, canvasY); 598 | 599 | if (options.grid.autoHighlight) 600 | { 601 | // clear auto-highlights 602 | for (var i = 0; i < highlights.length; ++i) 603 | { 604 | var h = highlights[i]; 605 | if (h.auto == eventname && !(item && h.series == item.series)) 606 | unhighlight(h.series); 607 | } 608 | } 609 | 610 | // highlight the slice 611 | if (item) 612 | highlight(item.series, eventname); 613 | 614 | // trigger any hover bind events 615 | var pos = { pageX: e.pageX, pageY: e.pageY }; 616 | target.trigger(eventname, [ pos, item ]); 617 | } 618 | 619 | function highlight(s, auto) 620 | { 621 | if (typeof s == "number") 622 | s = series[s]; 623 | 624 | var i = indexOfHighlight(s); 625 | if (i == -1) 626 | { 627 | highlights.push({ series: s, auto: auto }); 628 | plot.triggerRedrawOverlay(); 629 | } 630 | else if (!auto) 631 | highlights[i].auto = false; 632 | } 633 | 634 | function unhighlight(s) 635 | { 636 | if (s == null) 637 | { 638 | highlights = []; 639 | plot.triggerRedrawOverlay(); 640 | } 641 | 642 | if (typeof s == "number") 643 | s = series[s]; 644 | 645 | var i = indexOfHighlight(s); 646 | if (i != -1) 647 | { 648 | highlights.splice(i, 1); 649 | plot.triggerRedrawOverlay(); 650 | } 651 | } 652 | 653 | function indexOfHighlight(s) 654 | { 655 | for (var i = 0; i < highlights.length; ++i) 656 | { 657 | var h = highlights[i]; 658 | if (h.series == s) 659 | return i; 660 | } 661 | return -1; 662 | } 663 | 664 | function drawOverlay(plot, octx) 665 | { 666 | //alert(options.series.pie.radius); 667 | var options = plot.getOptions(); 668 | //alert(options.series.pie.radius); 669 | 670 | var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; 671 | 672 | octx.save(); 673 | octx.translate(centerLeft, centerTop); 674 | octx.scale(1, options.series.pie.tilt); 675 | 676 | for (i = 0; i < highlights.length; ++i) 677 | drawHighlight(highlights[i].series); 678 | 679 | drawDonutHole(octx); 680 | 681 | octx.restore(); 682 | 683 | function drawHighlight(series) 684 | { 685 | if (series.angle < 0) return; 686 | 687 | //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString(); 688 | octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor 689 | 690 | octx.beginPath(); 691 | if (Math.abs(series.angle - Math.PI*2) > 0.000000001) 692 | octx.moveTo(0,0); // Center of the pie 693 | octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false); 694 | octx.closePath(); 695 | octx.fill(); 696 | } 697 | 698 | } 699 | 700 | } // end init (plugin body) 701 | 702 | // define pie specific options and their default values 703 | var options = { 704 | series: { 705 | pie: { 706 | show: false, 707 | radius: 'auto', // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value) 708 | innerRadius:0, /* for donut */ 709 | startAngle: 3/2, 710 | tilt: 1, 711 | offset: { 712 | top: 0, 713 | left: 'auto' 714 | }, 715 | stroke: { 716 | color: '#FFF', 717 | width: 1 718 | }, 719 | label: { 720 | show: 'auto', 721 | formatter: function(label, slice){ 722 | return '
'+label+'
'+Math.round(slice.percent)+'%
'; 723 | }, // formatter function 724 | radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value) 725 | background: { 726 | color: null, 727 | opacity: 0 728 | }, 729 | threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow) 730 | }, 731 | combine: { 732 | threshold: -1, // percentage at which to combine little slices into one larger slice 733 | color: null, // color to give the new slice (auto-generated if null) 734 | label: 'Other' // label to give the new slice 735 | }, 736 | highlight: { 737 | //color: '#FFF', // will add this functionality once parseColor is available 738 | opacity: 0.5 739 | } 740 | } 741 | } 742 | }; 743 | 744 | $.plot.plugins.push({ 745 | init: init, 746 | options: options, 747 | name: "pie", 748 | version: "1.0" 749 | }); 750 | })(jQuery); 751 | -------------------------------------------------------------------------------- /js/jquery.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */ 2 | !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; 3 | }catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("