var global_pending_events = 0; function display_element(e, args) { var elem = document.getElementById(args.id); if (elem) elem.style.display = args.style; } function set_html(e, args) { var elem = document.getElementById(args.id); if (elem) elem.innerHTML = args.html; } function set_focus(e, args) { if (args.check_focused && focused) return; for (var i in args.id) { var id = args.id[i]; if (args.sel_id) id += this.getAttribute("sel_id"); var element = document.getElementById(id); if (element && element.offsetWidth) { if (!args.only_if_empty || !element.value || element.value.length == 0) element.focus(); break; } } } function show_by_feature(e, args) { var id = args.id; var feat = args.feat; var klfun = args.klfun; var style = args.style; var elem = document.getElementById(id); if (!elem) return; if (!feat) feat = id; if (!klfun) klfun = form_key_lookup; if (!style) style = ''; var f = split_setting(get_settings(feat, klfun, category_features)); if (f && f.show > 0) { elem.style.display = style; } else { elem.style.display = 'none'; } } /* * Registers all events to objects * (uses root so that object searching can be narrower) */ function register_events(events, root) { for (var event_id in events) { var current_event = events[event_id]; var elements = []; /* Get all involved elements */ if (current_event.id) { var element = root.getElementById(current_event.id); if (element) elements = [element]; } else if (current_event.name) { elements = root.getElementsByName(current_event.name); } else if (current_event.array_name) { var element; var i = 0; while (element = root.getElementsByName(current_event.array_name + '[' + i + ']')[0]) { elements[i++] = element; } } else if (current_event.array_id) { var element; var i = 0; while (element = root.getElementById(current_event.array_id + i)) { elements[i++] = element; } } /* Check if object exists to attach event to */ for (var element_index = 0; element_index < elements.length; element_index++) { var element = elements[element_index]; /* Init event id array */ if (!element.event_ids) element.event_ids = []; /* Check if current event already have been attached to the object */ if (isInArray(event_id, element.event_ids)) continue; /* Store current event id */ element.event_ids[element.event_ids.length] = event_id; /* Hijack the element, create an event array */ if (!element.events) element.events = []; /* Create array for each event trigger (Support for multiple events each event) */ if (!element.events[current_event.trigger]) element.events[current_event.trigger] = []; /* Store the event in the objects event array */ element.events[current_event.trigger][element.events[current_event.trigger].length] = current_event; /* Load events */ if (current_event.trigger == 'init') { call_event_timeout(element, 'init', 0); } else if (element.attachEvent) { /* Add an event listener to the object */ element.attachEvent("on" + current_event.trigger, /* The event trigger name */ call_event /* Event callback */ ); } else { element.addEventListener(current_event.trigger, /* The event trigger name */ call_event, /* Event callback */ true); /* Event bubbling */ } } } } /* * Event call back handler */ function call_event(e) { /* This element */ var element = this; var type = e.type; /* TODO srcElement is not necessarily the element we registered to. */ if (window.event) element = window.event.srcElement; if (element.asyncs > 0) { /* Already running, reschedule ourselves. */ call_event_timeout(element, type, 50); return; } global_pending_events++; element.asyncs = 1; /* Go through all events linked to the element event type */ for (var ep in element.events[type]) { var current_event = element.events[type][ep]; if (!current_event.bubble) { /* Don't do events below this object*/ if (window.event) { window.event.cancelBubble = true; } else if (e && e.stopPropagation) { e.stopPropagation(); } } /* Execute all actions in the current event */ for (var function_index in current_event.action) { var function_conf = current_event.action[function_index]; var f = eval(function_conf.name); var args = function_conf.args; /* * (element, f, args) need local binding within the higher order function. To bind them, we need to * create a higher higher order function and evalutate it to force the binding. */ var run_me = (function (element, f, args) { return (function () { /* Get function reference */ /* Execute function as if it was called by THIS, and send the event argument */ f.call(element, [element, type], args); }); })(element, f, args); if (function_conf.async) { global_pending_events++; element.asyncs++; run_me(); } else queue_document_change([element, type], run_me); run_me = null; } } global_pending_events--; if (--element.asyncs == 0) { run_document_changes(element); } } function queue_document_change(e, f) { var element = e[0]; if (!element.document_changes || element.document_changes === "") element.document_changes = []; element.document_changes[element.document_changes.length] = f; } function event_async_done(e) { var element = e[0]; var type = e[1]; global_pending_events--; element.asyncs--; if (element.asyncs == 0) { run_document_changes(element); } } function run_document_changes(element) { while (element.document_changes) { var to_run = element.document_changes; element.document_changes = ""; /* LIFO */ for (var i = to_run.length - 1; i >= 0; i--) { var f = to_run[i]; f(); } } } function call_event_timeout(element, type, time) { setTimeout(function() { call_event.call(element, {'type' : type}) }, time); }