diff options
author | mkanat%bugzilla.org <> | 2009-06-21 21:33:40 +0200 |
---|---|---|
committer | mkanat%bugzilla.org <> | 2009-06-21 21:33:40 +0200 |
commit | 6a23b8335dd9e0786cf2c6ea90c8574ac0c6f28f (patch) | |
tree | 09210e7401d57785effcc9b8bd86c2642f8a1d8d /js | |
parent | 4c3c583a411a59ae42df2652c8122fcfd5364c52 (diff) | |
download | bugzilla-6a23b8335dd9e0786cf2c6ea90c8574ac0c6f28f.tar.gz bugzilla-6a23b8335dd9e0786cf2c6ea90c8574ac0c6f28f.tar.xz |
Bug 463598: Improve the performance of the JavaScript that adjusts field values based on the value of another field
Patch by Max Kanat-Alexander <mkanat@bugzilla.org> r=wicked, a=mkanat
Diffstat (limited to 'js')
-rw-r--r-- | js/field.js | 117 |
1 files changed, 74 insertions, 43 deletions
diff --git a/js/field.js b/js/field.js index 629fb8a23..700c1de8d 100644 --- a/js/field.js +++ b/js/field.js @@ -389,40 +389,52 @@ function handleVisControllerValueChange(e, args) { } } -function showValueWhen(controlled_field_id, controlled_value, - controller_field_id, controller_value) +function showValueWhen(controlled_field_id, controlled_value_ids, + controller_field_id, controller_value_id) { var controller_field = document.getElementById(controller_field_id); // Note that we don't get an object for the controlled field here, // because it might not yet exist in the DOM. We just pass along its id. YAHOO.util.Event.addListener(controller_field, 'change', - handleValControllerChange, [controlled_field_id, controlled_value, - controller_field, controller_value]); + handleValControllerChange, [controlled_field_id, controlled_value_ids, + controller_field, controller_value_id]); } function handleValControllerChange(e, args) { var controlled_field = document.getElementById(args[0]); - var controlled_value = args[1]; + var controlled_value_ids = args[1]; var controller_field = args[2]; - var controller_value = args[3]; - - var item = getPossiblyHiddenOption(controlled_field, controlled_value); - if (bz_valueSelected(controller_field, controller_value)) { - showOptionInIE(item, controlled_field); - YAHOO.util.Dom.removeClass(item, 'bz_hidden_option'); - item.disabled = false; - } - else if (!item.disabled) { - YAHOO.util.Dom.addClass(item, 'bz_hidden_option'); - if (item.selected) { - item.selected = false; - bz_fireEvent(controlled_field, 'change'); + var controller_value_id = args[3]; + + var controller_item = document.getElementById( + _value_id(controller_field.id, controller_value_id)); + + for (var i = 0; i < controlled_value_ids.length; i++) { + var item = getPossiblyHiddenOption(controlled_field, + controlled_value_ids[i]); + if (item.disabled && controller_item && controller_item.selected) { + item = showOptionInIE(item, controlled_field); + YAHOO.util.Dom.removeClass(item, 'bz_hidden_option'); + item.disabled = false; + } + else if (!item.disabled) { + YAHOO.util.Dom.addClass(item, 'bz_hidden_option'); + if (item.selected) { + item.selected = false; + bz_fireEvent(controlled_field, 'change'); + } + item.disabled = true; + hideOptionInIE(item, controlled_field); } - item.disabled = true; - hideOptionInIE(item, controlled_field); } } +// A convenience function to generate the "id" tag of an <option> +// based on the numeric id that Bugzilla uses for that value. +function _value_id(field_name, id) { + return 'v' + id + '_' + field_name; +} + /*********************************/ /* Code for Hiding Options in IE */ /*********************************/ @@ -431,24 +443,50 @@ function handleValControllerChange(e, args) { * on <option> tags. However, you *can* insert a Comment Node as a * child of a <select> tag. So we just insert a Comment where the <option> * used to be. */ +var ie_hidden_options = new Array(); function hideOptionInIE(anOption, aSelect) { if (browserCanHideOptions(aSelect)) return; var commentNode = document.createComment(anOption.value); - aSelect.replaceChild(commentNode, anOption); + commentNode.id = anOption.id; + // This keeps the interface of Comments and Options the same for + // our other functions. + commentNode.disabled = true; + // replaceChild is very slow on IE in a <select> that has a lot of + // options, so we use replaceNode when we can. + if (anOption.replaceNode) { + anOption.replaceNode(commentNode); + } + else { + aSelect.replaceChild(commentNode, anOption); + } + + // Store the comment node for quick access for getPossiblyHiddenOption + if (!ie_hidden_options[aSelect.id]) { + ie_hidden_options[aSelect.id] = new Array(); + } + ie_hidden_options[aSelect.id][anOption.id] = commentNode; } function showOptionInIE(aNode, aSelect) { - if (browserCanHideOptions(aSelect)) return; - // If aNode is an Option - if (typeof(aNode.value) != 'undefined') return; + if (browserCanHideOptions(aSelect)) return aNode; // We do this crazy thing with innerHTML and createElement because // this is the ONLY WAY that this works properly in IE. var optionNode = document.createElement('option'); optionNode.innerHTML = aNode.data; optionNode.value = aNode.data; - var old_node = aSelect.replaceChild(optionNode, aNode); + optionNode.id = aNode.id; + // replaceChild is very slow on IE in a <select> that has a lot of + // options, so we use replaceNode when we can. + if (aNode.replaceNode) { + aNode.replaceNode(optionNode); + } + else { + aSelect.replaceChild(optionNode, aNode); + } + delete ie_hidden_options[aSelect.id][optionNode.id]; + return optionNode; } function initHidingOptionsForIE(select_name) { @@ -465,26 +503,19 @@ function initHidingOptionsForIE(select_name) { } } -function getPossiblyHiddenOption(aSelect, aValue) { - var val_index = bz_optionIndex(aSelect, aValue); - - /* We have to go fishing for one of our comment nodes if we - * don't find the <option>. */ - if (val_index < 0 && !browserCanHideOptions(aSelect)) { - var children = aSelect.childNodes; - for (var i = 0; i < children.length; i++) { - var item = children[i]; - if (item.data == aValue) { - // Set this for handleValControllerChange, so that both options - // and commentNodes have this. - children[i].disabled = true; - return children[i]; - } - } +function getPossiblyHiddenOption(aSelect, optionId) { + // Works always for <option> tags, and works for commentNodes + // in IE (but not in Webkit). + var id = _value_id(aSelect.id, optionId); + var val = document.getElementById(id); + + // This is for WebKit and other browsers that can't "display: none" + // an <option> and also can't getElementById for a commentNode. + if (!val && ie_hidden_options[aSelect.id]) { + val = ie_hidden_options[aSelect.id][id]; } - /* Otherwise we just return the Option we found. */ - return aSelect.options[val_index]; + return val; } var browser_can_hide_options; |