summaryrefslogtreecommitdiffstats
path: root/js
diff options
context:
space:
mode:
authormkanat%bugzilla.org <>2008-11-07 18:34:39 +0100
committermkanat%bugzilla.org <>2008-11-07 18:34:39 +0100
commit63be194996849202878c4a87e4c68a25d1976d3e (patch)
tree657fbe1458ce256015a832251219669070886e1e /js
parentebd2e3a29a893e1ea26899bac53296fc6422f47c (diff)
downloadbugzilla-63be194996849202878c4a87e4c68a25d1976d3e.tar.gz
bugzilla-63be194996849202878c4a87e4c68a25d1976d3e.tar.xz
Bug 308253: Ability to add select (enum) fields to a bug whose list of values depends on the value of another field
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=bbaetz, a=mkanat
Diffstat (limited to 'js')
-rw-r--r--js/field.js121
-rw-r--r--js/util.js34
2 files changed, 155 insertions, 0 deletions
diff --git a/js/field.js b/js/field.js
index fb8716872..daa390482 100644
--- a/js/field.js
+++ b/js/field.js
@@ -359,3 +359,124 @@ function handleVisControllerValueChange(e, args) {
YAHOO.util.Dom.addClass(field_container, 'bz_hidden_field');
}
}
+
+function showValueWhen(controlled_field_id, controlled_value,
+ controller_field_id, controller_value)
+{
+ 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]);
+}
+
+function handleValControllerChange(e, args) {
+ var controlled_field = document.getElementById(args[0]);
+ var controlled_value = 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');
+ }
+ item.disabled = true;
+ hideOptionInIE(item, controlled_field);
+ }
+}
+
+/*********************************/
+/* Code for Hiding Options in IE */
+/*********************************/
+
+/* IE 7 and below (and some other browsers) don't respond to "display: none"
+ * 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. */
+function hideOptionInIE(anOption, aSelect) {
+ if (browserCanHideOptions(aSelect)) return;
+
+ var commentNode = document.createComment(anOption.value);
+ aSelect.replaceChild(commentNode, anOption);
+}
+
+function showOptionInIE(aNode, aSelect) {
+ if (browserCanHideOptions(aSelect)) return;
+ // If aNode is an Option
+ if (typeof(aNode.value) != 'undefined') return;
+
+ // 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);
+}
+
+function initHidingOptionsForIE(select_name) {
+ var aSelect = document.getElementById(select_name);
+ if (browserCanHideOptions(aSelect)) return;
+
+ for (var i = 0; ;i++) {
+ var item = aSelect.options[i];
+ if (!item) break;
+ if (item.disabled) {
+ hideOptionInIE(item, aSelect);
+ i--; // Hiding an option means that the options array has changed.
+ }
+ }
+}
+
+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];
+ }
+ }
+ }
+
+ /* Otherwise we just return the Option we found. */
+ return aSelect.options[val_index];
+}
+
+var browser_can_hide_options;
+function browserCanHideOptions(aSelect) {
+ /* As far as I can tell, browsers that don't hide <option> tags
+ * also never have a X position for <option> tags, even if
+ * they're visible. This is the only reliable way I found to
+ * differentiate browsers. So we create a visible option, see
+ * if it has a position, and then remove it. */
+ if (typeof(browser_can_hide_options) == "undefined") {
+ var new_opt = bz_createOptionInSelect(aSelect, '', '');
+ var opt_pos = YAHOO.util.Dom.getX(new_opt);
+ aSelect.removeChild(new_opt);
+ if (opt_pos) {
+ browser_can_hide_options = true;
+ }
+ else {
+ browser_can_hide_options = false;
+ }
+ }
+ return browser_can_hide_options;
+}
+
+/* (end) option hiding code */
diff --git a/js/util.js b/js/util.js
index feef8fe41..86924210c 100644
--- a/js/util.js
+++ b/js/util.js
@@ -219,3 +219,37 @@ function bz_valueSelected(aSelect, aValue) {
return false;
}
+/**
+ * Tells you where (what index) in a <select> a particular option is.
+ * Returns -1 if the value is not in the <select>
+ *
+ * @param aSelect The select you're checking.
+ * @param aValue The value you want to know the index of.
+ */
+function bz_optionIndex(aSelect, aValue) {
+ for (var i = 0; i < aSelect.options.length; i++) {
+ if (aSelect.options[i].value == aValue) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Used to fire an event programmatically.
+ *
+ * @param anElement The element you want to fire the event of.
+ * @param anEvent The name of the event you want to fire,
+ * without the word "on" in front of it.
+ */
+function bz_fireEvent(anElement, anEvent) {
+ // IE
+ if (document.createEventObject) {
+ var evt = document.createEventObject();
+ return anElement.fireEvent('on' + anEvent, evt);
+ }
+ // Firefox, etc.
+ var evt = document.createEvent("HTMLEvents");
+ evt.initEvent(anEvent, true, true); // event type, bubbling, cancelable
+ return !anElement.dispatchEvent(evt);
+}