r=dkl,a=LpSolit git-svn-id: svn://10.0.0.236/trunk@264476 18797224-902f-48f8-a5cc-f745e15eee43
345 lines
12 KiB
JavaScript
345 lines
12 KiB
JavaScript
/* 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.
|
|
*/
|
|
|
|
var PAREN_INDENT_EM = 2;
|
|
var ANY_ALL_SELECT_CLASS = 'any_all_select';
|
|
|
|
// When somebody chooses to "Hide Advanced Features" for Custom Search,
|
|
// we don't want to hide "Not" checkboxes if they've been checked. We
|
|
// accomplish this by removing the custom_search_advanced class from Not
|
|
// checkboxes when they are checked.
|
|
//
|
|
// We never add the custom_search_advanced class back. If we did, TUI
|
|
// would get confused in this case: Check Not, Hide Advanced Features,
|
|
// Uncheck Not, Show Advanced Features. (It hides "Not" when it shouldn't.)
|
|
function custom_search_not_changed(id) {
|
|
var container = document.getElementById('custom_search_not_container_' + id);
|
|
YAHOO.util.Dom.removeClass(container, 'custom_search_advanced');
|
|
|
|
fix_query_string(container);
|
|
}
|
|
|
|
function custom_search_new_row() {
|
|
var row = document.getElementById('custom_search_last_row');
|
|
var clone = row.cloneNode(true);
|
|
|
|
_cs_fix_row_ids(clone);
|
|
|
|
// We only want one copy of the buttons, in the new row. So the old
|
|
// ones get deleted.
|
|
var op_button = document.getElementById('op_button');
|
|
row.removeChild(op_button);
|
|
var cp_button = document.getElementById('cp_container');
|
|
row.removeChild(cp_button);
|
|
var add_button = document.getElementById('add_button');
|
|
row.removeChild(add_button);
|
|
_remove_any_all(clone);
|
|
|
|
// Always make sure there's only one row with this id.
|
|
row.id = null;
|
|
row.parentNode.appendChild(clone);
|
|
cs_reconfigure(row);
|
|
fix_query_string(row);
|
|
return clone;
|
|
}
|
|
|
|
var _cs_source_any_all;
|
|
function custom_search_open_paren() {
|
|
var row = document.getElementById('custom_search_last_row');
|
|
|
|
// create a copy of j_top and use that as the source, so we can modify
|
|
// j_top if required
|
|
if (!_cs_source_any_all) {
|
|
var j_top = document.getElementById('j_top');
|
|
_cs_source_any_all = j_top.cloneNode(true);
|
|
}
|
|
|
|
// find the parent any/all select, and remove the grouped option
|
|
var structure = _cs_build_structure(row);
|
|
var old_id = _cs_get_row_id(row);
|
|
var parent_j = document.getElementById(_cs_get_join(structure, 'f' + old_id));
|
|
_cs_remove_and_g(parent_j);
|
|
|
|
// If there's an "Any/All" select in this row, it needs to stay as
|
|
// part of the parent paren set.
|
|
var old_any_all = _remove_any_all(row);
|
|
if (old_any_all) {
|
|
var any_all_row = row.cloneNode(false);
|
|
any_all_row.id = null;
|
|
any_all_row.appendChild(old_any_all);
|
|
row.parentNode.insertBefore(any_all_row, row);
|
|
}
|
|
|
|
// We also need a "Not" checkbox to stay in the parent paren set.
|
|
var new_not = YAHOO.util.Dom.getElementsByClassName(
|
|
'custom_search_not_container', null, row);
|
|
var not_for_paren = new_not[0].cloneNode(true);
|
|
|
|
// Preserve the values when modifying the row.
|
|
var id = _cs_fix_row_ids(row, true);
|
|
var prev_id = id - 1;
|
|
|
|
var paren_row = row.cloneNode(false);
|
|
paren_row.id = null;
|
|
paren_row.innerHTML = '(<input type="hidden" name="f' + prev_id
|
|
+ '" id="f' + prev_id + '" value="OP">';
|
|
paren_row.insertBefore(not_for_paren, paren_row.firstChild);
|
|
row.parentNode.insertBefore(paren_row, row);
|
|
|
|
// New paren set needs a new "Any/All" select.
|
|
var any_all_container = document.createElement('div');
|
|
YAHOO.util.Dom.addClass(any_all_container, ANY_ALL_SELECT_CLASS);
|
|
var any_all = _cs_source_any_all.cloneNode(true);
|
|
any_all.name = 'j' + prev_id;
|
|
any_all.id = any_all.name;
|
|
any_all_container.appendChild(any_all);
|
|
row.insertBefore(any_all_container, row.firstChild);
|
|
|
|
var margin = YAHOO.util.Dom.getStyle(row, 'margin-left');
|
|
var int_match = margin.match(/\d+/);
|
|
var new_margin = parseInt(int_match[0]) + PAREN_INDENT_EM;
|
|
YAHOO.util.Dom.setStyle(row, 'margin-left', new_margin + 'em');
|
|
YAHOO.util.Dom.removeClass('cp_container', 'bz_default_hidden');
|
|
|
|
cs_reconfigure(any_all_container);
|
|
fix_query_string(any_all_container);
|
|
}
|
|
|
|
function custom_search_close_paren() {
|
|
var new_row = custom_search_new_row();
|
|
|
|
// We need to up the new row's id by one more, because we're going
|
|
// to insert a "CP" before it.
|
|
var id = _cs_fix_row_ids(new_row);
|
|
|
|
var margin = YAHOO.util.Dom.getStyle(new_row, 'margin-left');
|
|
var int_match = margin.match(/\d+/);
|
|
var new_margin = parseInt(int_match[0]) - PAREN_INDENT_EM;
|
|
YAHOO.util.Dom.setStyle(new_row, 'margin-left', new_margin + 'em');
|
|
|
|
var paren_row = new_row.cloneNode(false);
|
|
paren_row.id = null;
|
|
paren_row.innerHTML = ')<input type="hidden" name="f' + (id - 1)
|
|
+ '" id="f' + (id - 1) + '" value="CP">';
|
|
|
|
new_row.parentNode.insertBefore(paren_row, new_row);
|
|
|
|
if (new_margin == 0) {
|
|
YAHOO.util.Dom.addClass('cp_container', 'bz_default_hidden');
|
|
}
|
|
|
|
cs_reconfigure(new_row);
|
|
fix_query_string(new_row);
|
|
}
|
|
|
|
// When a user goes Back in their browser after searching, some browsers
|
|
// (Chrome, as of September 2011) do not remember the DOM that was created
|
|
// by the Custom Search JS. (In other words, their whole entered Custom
|
|
// Search disappears.) The solution is to update the History object,
|
|
// using the query string, which query.cgi can read to re-create the page
|
|
// exactly as the user had it before.
|
|
function fix_query_string(form_member) {
|
|
// window.History comes from history.js.
|
|
// It falls back to the normal window.history object for HTML5 browsers.
|
|
if (!(window.History && window.History.replaceState))
|
|
return;
|
|
|
|
var form = YAHOO.util.Dom.getAncestorByTagName(form_member, 'form');
|
|
// Disable the token field so setForm doesn't include it
|
|
var reenable_token = false;
|
|
if (form['token'] && !form['token'].disabled) {
|
|
form['token'].disabled = true;
|
|
reenable_token = true;
|
|
}
|
|
var query = YAHOO.util.Connect.setForm(form);
|
|
if (reenable_token)
|
|
form['token'].disabled = false;
|
|
window.History.replaceState(null, document.title, '?' + query);
|
|
}
|
|
|
|
// Browsers that do not support HTML5's history.replaceState gain an emulated
|
|
// version via history.js, with the full query_string in the location's hash.
|
|
// We rewrite the URL to include the hash and redirect to the new location,
|
|
// which causes custom search fields to work.
|
|
function redirect_html4_browsers() {
|
|
var hash = document.location.hash;
|
|
if (hash == '') return;
|
|
hash = hash.substring(1);
|
|
if (hash.substring(0, 10) != 'query.cgi?') return;
|
|
var url = document.location + "";
|
|
url = url.substring(0, url.indexOf('query.cgi#')) + hash;
|
|
document.location = url;
|
|
}
|
|
|
|
function _cs_fix_row_ids(row, preserve_values) {
|
|
// Update the label of the checkbox.
|
|
var label = YAHOO.util.Dom.getElementBy(function() { return true }, 'label', row);
|
|
var id_match = label.htmlFor.match(/\d+$/);
|
|
var id = parseInt(id_match[0]) + 1;
|
|
label.htmlFor = label.htmlFor.replace(/\d+$/, id);
|
|
|
|
// Sets all the inputs in the row back to their default
|
|
// and fixes their id.
|
|
var fields =
|
|
YAHOO.util.Dom.getElementsByClassName('custom_search_form_field', null, row);
|
|
for (var i = 0; i < fields.length; i++) {
|
|
var field = fields[i];
|
|
|
|
if (!preserve_values) {
|
|
if (field.type == "checkbox") {
|
|
field.checked = false;
|
|
}
|
|
else {
|
|
field.value = '';
|
|
}
|
|
}
|
|
|
|
// Update the numeric id for the row.
|
|
field.name = field.name.replace(/\d+$/, id);
|
|
field.id = field.name;
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
function _cs_build_structure(form_member) {
|
|
// build a map of the structure of the custom fields
|
|
var form = YAHOO.util.Dom.getAncestorByTagName(form_member, 'form');
|
|
var last_id = _get_last_cs_row_id(form);
|
|
var structure = [ 'j_top' ];
|
|
var nested = [ structure ];
|
|
for (var id = 1; id <= last_id; id++) {
|
|
var f = form['f' + id];
|
|
if (!f || !f.parentNode.parentNode) continue;
|
|
|
|
if (f.value == 'OP') {
|
|
var j = [ 'j' + id ];
|
|
nested[nested.length - 1].push(j);
|
|
nested.push(j);
|
|
continue;
|
|
} else if (f.value == 'CP') {
|
|
nested.pop();
|
|
continue;
|
|
} else {
|
|
nested[nested.length - 1].push('f' + id);
|
|
}
|
|
}
|
|
return structure;
|
|
}
|
|
|
|
function cs_reconfigure(form_member) {
|
|
var structure = _cs_build_structure(form_member);
|
|
_cs_add_listeners(structure);
|
|
_cs_trigger_j_listeners(structure);
|
|
fix_query_string(form_member);
|
|
|
|
var j = _cs_get_join(structure, 'f' + _get_last_cs_row_id());
|
|
document.getElementById('op_button').disabled = document.getElementById(j).value == 'AND_G';
|
|
}
|
|
|
|
function _cs_add_listeners(parents) {
|
|
for (var i = 0, l = parents.length; i < l; i++) {
|
|
if (typeof(parents[i]) == 'object') {
|
|
// nested
|
|
_cs_add_listeners(parents[i]);
|
|
} else if (i == 0) {
|
|
// joiner
|
|
YAHOO.util.Event.removeListener(parents[i], 'change', _cs_j_change);
|
|
YAHOO.util.Event.addListener(parents[i], 'change', _cs_j_change, parents);
|
|
} else {
|
|
// field
|
|
YAHOO.util.Event.removeListener(parents[i], 'change', _cs_f_change);
|
|
YAHOO.util.Event.addListener(parents[i], 'change', _cs_f_change, parents);
|
|
}
|
|
}
|
|
}
|
|
|
|
function _cs_trigger_j_listeners(fields) {
|
|
var has_children = false;
|
|
for (var i = 0, l = fields.length; i < l; i++) {
|
|
if (typeof(fields[i]) == 'undefined') {
|
|
continue;
|
|
} else if (typeof(fields[i]) == 'object') {
|
|
// nested
|
|
_cs_trigger_j_listeners(fields[i]);
|
|
has_children = true;
|
|
} else if (i == 0) {
|
|
_cs_j_change(undefined, fields);
|
|
}
|
|
}
|
|
if (has_children) {
|
|
_cs_remove_and_g(document.getElementById(fields[0]));
|
|
}
|
|
}
|
|
|
|
function _cs_get_join(parents, field) {
|
|
for (var i = 0, l = parents.length; i < l; i++) {
|
|
if (typeof(parents[i]) == 'object') {
|
|
// nested
|
|
var result = _cs_get_join(parents[i], field);
|
|
if (result) return result;
|
|
} else if (parents[i] == field) {
|
|
return parents[0];
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function _cs_remove_and_g(join_field) {
|
|
var index = bz_optionIndex(join_field, 'AND_G');
|
|
join_field.options[index] = null;
|
|
join_field.options[bz_optionIndex(join_field, 'AND')].innerHTML = cs_and_label;
|
|
join_field.options[bz_optionIndex(join_field, 'OR')].innerHTML = cs_or_label;
|
|
}
|
|
|
|
function _cs_j_change(evt, fields, field) {
|
|
var j = document.getElementById(fields[0]);
|
|
if (j && j.value == 'AND_G') {
|
|
for (var i = 1, l = fields.length; i < l; i++) {
|
|
if (typeof(fields[i]) == 'object') continue;
|
|
if (!field) {
|
|
field = document.getElementById(fields[i]).value;
|
|
} else {
|
|
document.getElementById(fields[i]).value = field;
|
|
}
|
|
}
|
|
if (evt) {
|
|
fix_query_string(j);
|
|
}
|
|
if ('f' + _get_last_cs_row_id() == fields[fields.length - 1]) {
|
|
document.getElementById('op_button').style.display = 'none';
|
|
}
|
|
} else {
|
|
document.getElementById('op_button').style.display = '';
|
|
}
|
|
}
|
|
|
|
function _cs_f_change(evt, args) {
|
|
var field = YAHOO.util.Event.getTarget(evt);
|
|
_cs_j_change(evt, args, field.value);
|
|
}
|
|
|
|
function _get_last_cs_row_id() {
|
|
return _cs_get_row_id('custom_search_last_row');
|
|
}
|
|
|
|
function _cs_get_row_id(row) {
|
|
var label = YAHOO.util.Dom.getElementBy(function() { return true }, 'label', row);
|
|
return parseInt(label.htmlFor.match(/\d+$/)[0]);
|
|
}
|
|
|
|
function _remove_any_all(parent) {
|
|
var any_all = YAHOO.util.Dom.getElementsByClassName(
|
|
ANY_ALL_SELECT_CLASS, null, parent);
|
|
if (any_all[0]) {
|
|
parent.removeChild(any_all[0]);
|
|
return any_all[0];
|
|
}
|
|
return null;
|
|
}
|