This repository has been archived on 2024-11-28. You can view files and clone it, but cannot push or open issues or pull requests.
Incam_SGD/resources/js/constructed_search.js

242 lines
9.1 KiB
JavaScript

// simple event stacking.
// i don't like Mochikit's one.
function attachToElementEvent(elem, event_name, func) {
// catch IE (grumble)
if (elem.attachEvent) {
elem.attachEvent('on'+event_name, func);
} else {
elem.addEventListener(event_name, func, false);
}
}
function removeFromElementEvent(elem, event_name, func) {
// catch IE (grumble)
if (elem.detachEvent) {
elem.detachEvent('on'+event_name, func);
} else {
elem.removeEventListener(event_name, func, false);
}
}
var booleanGroups = Array();
function getBooleanGroupId(table) {
for (var i=0; i<booleanGroups.length; i++) {
if (booleanGroups[i] == table) {
return i;
}
}
// nothing found.
simpleLog('DEBUG','no entry found for table.');
booleanGroups.push(table);
simpleLog('DEBUG','added entry at '+(booleanGroups.length-1));
return booleanGroups.length-1; // int loc.
}
// quick and dirty helper - find the nearest parent item matching tagName.
// FIXME steal the klass or tagName logic from MochiK.
function breadcrumbFind(elem, tagName) {
var stopTag = 'BODY';
var currentTag = elem.tagName;
var currentElem = elem;
while ((currentTag != stopTag) && (currentTag != tagName)) {
currentElem = currentElem.parentNode;
currentTag = currentElem.tagName;
}
if (currentTag == tagName) {
return currentElem;
} else {
return null;
}
}
var autoIndexCriteria = Array();
// initiate the criteria creation process.
function addNewCriteria(add_button) {
var parent_row = breadcrumbFind(add_button, 'TR');
var parent_table = breadcrumbFind(parent_row, 'TABLE');
simpleLog('DEBUG','addNewCriteria found parent row: '+parent_row);
simpleLog('DEBUG','addNewCriteria found parent table: '+parent_table);
var select_source = parent_row.getElementsByTagName('select');
if (select_source.length == 0) {
simpleLog('ERROR','addNewCriteria found no criteria specification source.: '+parent_row);
} else {
var select = select_source[0];
}
var notify_source = parent_row.getElementsByTagName('p');
if (notify_source.length == 0) {
simpleLog('ERROR','addNewCriteria found no message storage in row: '+parent_row);
} else {
var notify_message = notify_source[0];
}
// make this one identifiable.
autoIndexCriteria.push(0);
var critId = autoIndexCriteria.length;
var tableId = getBooleanGroupId(parent_table);
simpleLog('DEBUG','got boolean group id'+tableId);
// ok, warn the user that we\'re loading the item.
replaceChildNodes(notify_message, _('loading...'));
var newCriteriaText = scrapeText(select.options[select.selectedIndex])+' '; // FIXME insert the "input" here.
replaceChildNodes(select.parentNode, newCriteriaText, INPUT({'type':'hidden', 'name':'boolean_search[subgroup]['+tableId+'][values]['+critId+'][type]','value':select.value})); // works thanks to DOM co-ercion.
createAdditionalCriteriaOption(parent_table);
var removeButton = INPUT({'type':'button', 'value':_('Remove')});
attachToElementEvent(removeButton, 'click', partial(removeCriteria, removeButton));
add_button.parentNode.replaceChild(removeButton, add_button);
// fetch.
var dest_cell = notify_message.parentNode;
var baseUrl = getElement('kt-core-baseurl').value;
var targeturl = baseUrl + '/search/ajaxBooleanSearch.php?action=getNewCriteria&type='+select.value+'&critId='+critId;
simpleLog('DEBUG','addNewCriteria initiating request to: '+targeturl);
var deferred = doSimpleXMLHttpRequest(targeturl);
deferred.addCallbacks(partial(do_addNewCriteria, dest_cell, critId, tableId), handleAjaxError);
}
// FIXME multi-select items using PHP array[] syntax won't work. we'd need to:
// - check for the presence of [ or ]. if so, use everything before [ as
// the key, and append everything after [.
// actually replace the contents of the specified td with the responseText.
function do_addNewCriteria(destination_cell, crit_id, table_id, req) {
simpleLog('DEBUG','replacing content of cell with: \n'+req.responseText);
destination_cell.innerHTML = req.responseText;
// whatever was passed in almost certainly has the wrong name, but that's what
// will be expected in the backend.
// wrap it so we don't get clashes.
var inputs = destination_cell.getElementsByTagName('INPUT');
var selects = destination_cell.getElementsByTagName('SELECT');
for (var i=0; i<inputs.length; i++) {
var obj = inputs[i];
obj.name = "boolean_search[subgroup]["+table_id+"][values]["+crit_id+"][data]["+obj.name+"]";
if(obj.getAttribute("type") == "checkbox" && obj.getAttribute("class") == "multiple")
{
obj.name = obj.name+"[]";
}
}
for (var i=0; i<selects.length; i++) {
var obj = selects[i];
obj.name = "boolean_search[subgroup]["+table_id+"][values]["+crit_id+"][data]["+obj.name+"]";
if(obj.getAttribute("multiple") == "multiple")
{
obj.name = obj.name+"[]";
}
}
simpleLog('DEBUG','criteria addition complete.');
}
function handleAjaxError(err) {
simpleLog('ERROR','ajax error: '+err);
}
function removeCriteria(removeButton) {
var parent_row = breadcrumbFind(removeButton, 'TR');
if (parent_row == null) {
simpleLog('ERROR','removeCriteria found no effective parent row.');
} else {
parent_row.parentNode.removeChild(parent_row);
}
simpleLog('DEBUG','criteria removed.');
}
function createAdditionalCriteriaOption(parent_table) {
var tbody = getSearchContainer(parent_table);
if (tbody == null) {
simpleLog('ERROR','createAdditionalCriteriaOption: No criteria table found.');
return null;
}
// now we need to instantiate the selection stuff.
// to do this we find a hidden div in the page which contains the container types...
var master_div = getElement('search-criteria-container');
if (master_div == null) {
simpleLog('ERROR','createAdditionalCriteriaOption: No criteria types identified within the request.');
return null;
}
// clone, and append.
var clonedObject = master_div.getElementsByTagName('select')[0].cloneNode(true);
var select_entry = TD(null, clonedObject);
var notification_entry = TD(null, createDOM('P',{'class':'helpText'},_('first select a type of query')));
var add_button = INPUT({'type':'button', 'value':_('Add')});
attachToElementEvent(add_button, 'click', partial(addNewCriteria, add_button));
var add_entry = TD(null, add_button);
tbody.appendChild(TR(null, select_entry, notification_entry, add_entry));
}
function getSearchContainer(parent_table) {
var container = parent_table;
if (container == null) {
simpleLog('ERROR','No criteria table found.');
return null;
} else {
var innerContainer = container.getElementsByTagName('TBODY');
}
if (innerContainer.length == 0) {
simpleLog('ERROR','No criteria tbody found.');
return null;
} else {
var container = innerContainer[0];
delete innerContainer;
}
return container;
}
// uses addbutton to insertBefore
function addBooleanGroup(addbutton) {
bodyObj = addbutton.parentNode;
simpleLog('DEBUG','adding boolean group to '+bodyObj);
// i hate me. i also want sane multiline
sourceString = ' <fieldset> <legend>' + _('Criteria Group') + '</legend> <table class="advanced-search-form"> <tbody> <tr> <th>'+_('Criteria')+'</th> <th>'+_('Values')+'</th> </tr></tbody></table> </fieldset>';
// add the fieldset
var t = DIV(null);
t.innerHTML = sourceString; // urgh.
var fieldsetObj = t.getElementsByTagName('FIELDSET')[0];
bodyObj.insertBefore(fieldsetObj, addbutton);
tableObj = fieldsetObj.getElementsByTagName('TABLE')[0];
// get an id for the table.
var table_id = getBooleanGroupId(tableObj);
// add the grouping string
groupingString = '<p class="helpText">' + _('Return items which match')+' &nbsp;<select name="boolean_search[subgroup]['+table_id+'][join]"><option value="AND">'+_('all')+'</option><option value="OR">'+_('any')+'</option></select>'+_('of the criteria specified.')+'</p>';
t = DIV(null);
t.innerHTML = groupingString;
var paraObj = t.getElementsByTagName('P')[0];
fieldsetObj.insertBefore(paraObj, tableObj);
// add a basic item to the table.
createAdditionalCriteriaOption(tableObj);
// done.
simpleLog('DEBUG','done adding boolean group.');
}
// FIXME do we want a "remove boolean group" setting?
// FIXME yes, and its easy (find parent, find ITS parent, toast.)
function initialiseChecks() {
var initialTables = getElementsByTagAndClassName('TABLE','advanced-search-form');
simpleLog('DEBUG','initialising '+initialTables.length+' criteria groups.');
var t = TABLE(null);
for (var i=0; i<initialTables.length; i++) {
if (typeof(initialTables[i]) == typeof(t)) {
getBooleanGroupId(initialTables[i]);
}
}
}
addLoadEvent(initialiseChecks);