/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * This Source Code Form is "Incompatible With Secondary Licenses", as * defined by the Mozilla Public License, v. 2.0. */ $(function() { 'use strict'; // all keywords for autocompletion (lazy-loaded on edit) var keywords = []; // products with descriptions (also lazy-loaded) var products = []; // scroll to an element function scroll_to(el, complete) { var offset = el.offset(); $('html, body') .animate({ scrollTop: offset.top - 20, scrollLeft: offset.left = 20 }, 200, complete ); } // expand/collapse module function slide_module(module, action) { var latch = module.find('.module-latch'); var spinner = $(latch.children('.module-spinner')[0]); var content = $(module.children('.module-content')[0]); function slide_done() { spinner.html(content.is(':visible') ? '▾' : '▸'); } if (action == 'show') { content.slideDown(200, 'swing', slide_done); } else if (action == 'hide') { content.slideUp(200, 'swing', slide_done); } else { content.slideToggle(200, 'swing', slide_done); } } // expand all modules $('#expand-all-btn') .click(function(event) { event.preventDefault(); var btn = $(event.target); var modules; if (btn.data('expanded-modules')) { modules = btn.data('expanded-modules'); btn.data('expanded-modules', false); modules.each(function() { slide_module($(this).parent('.module')); }); btn.text('Expand All'); } else { modules = $('.module-content:hidden'); btn.data('expanded-modules', modules); modules.each(function() { slide_module($(this).parent('.module')); }); btn.text('Collapse'); } }); // expand/colapse module $('.module-header') .click(function(event) { event.preventDefault(); slide_module($(this).parents('.module')); }); // toggle obsolete attachments $('#attachments-obsolete-btn') .click(function(event) { event.preventDefault(); $(event.target).text(($('#attachments tr:hidden').length ? 'Hide' : 'Show') + ' Obsolete Attachments'); $('#attachments tr.attach-obsolete').toggle(); }); // comment collapse/expand $('.comment-spinner') .click(function(event) { event.preventDefault(); var spinner = $(event.target); var id = spinner.attr('id').match(/\d+$/)[0]; // switch to full header for initially collapsed comments if (spinner.attr('id').match(/^ccs-/)) { $('#cc-' + id).hide(); $('#ch-' + id).show(); } $('#ct-' + id).slideToggle('fast', function() { $('#c' + id).find('.activity').toggle(); spinner.text($('#ct-' + id + ':visible').length ? '-' : '+'); }); }); // url --> unsafe warning $('.unsafe-url') .click(function(event) { event.preventDefault(); if (confirm('This is considered an unsafe URL and could possibly be harmful. ' + 'The full URL is:\n\n' + $(event.target).attr('title') + '\n\nContinue?')) { try { window.open($(event.target).attr('title')); } catch(ex) { alert('Malformed URL'); } } }); // last comment btn $('#last-comment-btn') .click(function(event) { event.preventDefault(); var id = $('.comment:last')[0].parentNode.id; scroll_to($('#' + id)); window.location.hash = id; }); // top btn $('#top-btn') .click(function(event) { event.preventDefault(); scroll_to($('body')); }); // use non-native tooltips for relative times and bug summaries $('.rel-time, .rel-time-title, .bz_bug_link, .tt').tooltip({ position: { my: "left top+8", at: "left bottom", collision: "flipfit" }, show: { effect: 'none' }, hide: { effect: 'none' } }); // tooltips create a new ui-helper-hidden-accessible div each time a // tooltip is shown. this is never removed leading to memory leak and // bloated dom. http://bugs.jqueryui.com/ticket/10689 $('.ui-helper-hidden-accessible').remove(); // product/component info $('.spin-toggle, #product-latch, #component-latch') .click(function(event) { event.preventDefault(); var latch = $($(event.target).data('latch')); var el_for = $($(event.target).data('for')); if (latch.data('expanded')) { latch.data('expanded', false).html('▸'); el_for.hide(); } else { latch.data('expanded', true).html('▾'); el_for.show(); } }); // cc list $('#cc-latch, #cc-summary') .click(function(event) { event.preventDefault(); var latch = $('#cc-latch'); if (latch.data('expanded')) { latch.data('expanded', false).html('▸'); $('#cc-list').hide(); } else { latch.data('expanded', true).html('▾'); $('#cc-list').show(); if (!latch.data('fetched')) { $('#cc-list').html( ' Loading...' ); bugzilla_ajax( { url: 'rest/bug_modal/cc/' + BUGZILLA.bug_id }, function(data) { $('#cc-list').html(data.html); latch.data('fetched', true); } ); } } }); // copy summary to clipboard if ($('#copy-summary').length) { var zero = new ZeroClipboard($('#copy-summary')); zero.on({ 'error': function(event) { console.log(event.message); zero.destroy(); $('#copy-summary').hide(); }, 'copy': function(event) { var clipboard = event.clipboardData; clipboard.setData('text/plain', 'Bug ' + BUGZILLA.bug_id + ' - ' + $('#field-value-short_desc').text()); } }); } // lightboxes $('.lightbox, .comment-text .lightbox + span:first-of-type a:first-of-type') .click(function(event) { if (event.metaKey) return; event.preventDefault(); lb_show(this); }); // when copying the bug id and summary, reformat to remove \n and alias $(document).on( 'copy', function(event) { var selection = document.getSelection().toString().trim(); var match = selection.match(/^(Bug \d+)\s*\n(.+)$/) || selection.match(/^(Bug \d+)\s+\([^\)]+\)\s*\n(.+)$/); if (match) { var content = match[1] + ' - ' + match[2].trim(); if (event.originalEvent.clipboardData) { event.originalEvent.clipboardData.setData('text/plain', content); } else if (window.clipboardData) { window.clipboardData.setData('Text', content); } else { return; } event.preventDefault(); } }); // // anything after this point is only executed for logged in users // if (BUGZILLA.user.id === 0) return; // edit/save mode button $('#mode-btn') .click(function(event) { event.preventDefault(); // hide buttons, old error messages $('#mode-btn-readonly').hide(); // toggle visibility $('.edit-hide').hide(); $('.edit-show').show(); // expand specific modules $('#module-details .module-header').each(function() { if ($(this.parentNode).find('.module-content:visible').length === 0) { $(this).click(); } }); // if there's no current user-story, it's a better experience if it's editable by default if ($('#cf_user_story').val() === '') { $('#user-story-edit-btn').click(); } // "loading.." ui $('#mode-btn-loading').show(); $('#cancel-btn').prop('disabled', true); $('#mode-btn').prop('disabled', true); // load the missing select data bugzilla_ajax( { url: 'rest/bug_modal/edit/' + BUGZILLA.bug_id }, function(data) { $('#mode-btn').hide(); // populate select menus $.each(data.options, function(key, value) { var el = $('#' + key); if (!el) return; var selected = el.val(); el.empty(); $(value).each(function(i, v) { el.append($('