/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * UI utility functions. */ var ui = {}; /** * Return a child element of a node with the given id. */ ui.elementByID = function(node, id) { if (node.skipNode == true) return null; for (var i in node.childNodes) { var child = node.childNodes[i]; if (child.id == id) return child; var gchild = ui.elementByID(child, id); if (gchild != null) return gchild; } return null; }; /** * Return the current document, or a child element with the given id. */ function $(id) { if (id == document) return document; return ui.elementByID($(document), id); }; /** * Return the query string of a URL. */ ui.query = function(url) { var u = '' + url; var q = u.indexOf('?'); return q >= 0? u.substring(q + 1) : ''; }; /** * Return the fragment part of a URL. */ ui.fragment = function(url) { var u = '' + url; var h = u.indexOf('#'); return h >= 0? u.substring(h + 1) : ''; }; /** * Return the path and parameters of a URL. */ ui.pathandparams = function(url) { var u = '' + url; var ds = u.indexOf('//'); var u2 = ds > 0? u.substring(ds + 2) : u; var s = u2.indexOf('/'); return s > 0? u2.substring(s) : ''; }; /** * Return a dictionary of query parameters in a URL. */ ui.queryParams = function(url) { var qp = new Array(); var qs = ui.query(url).split('&'); for (var i = 0; i < qs.length; i++) { var e = qs[i].indexOf('='); if (e > 0) qp[qs[i].substring(0, e)] = unescape(qs[i].substring(e + 1)); } return qp; }; /** * Return a dictionary of fragment parameters in a URL. */ ui.fragmentParams = function(url) { var qp = new Array(); var qs = ui.fragment(url).split('&'); for (var i = 0; i < qs.length; i++) { var e = qs[i].indexOf('='); if (e > 0) qp[qs[i].substring(0, e)] = unescape(qs[i].substring(e + 1)); } return qp; }; /** * Convert a base64-encoded image to a data URL. */ ui.b64img = function(b64) { return 'data:image/png;base64,' + b64; }; /** * Declare a CSS stylesheet. */ ui.declareCSS = function(s) { var e = document.createElement('style'); e.type = 'text/css'; e.textContent = s; return e; }; /** * Declare a script. */ ui.declareScript = function(s) { var e = document.createElement('script'); e.type = 'text/javascript'; e.text = s; return e; }; /** * Return the scripts elements under a given element. */ ui.innerScripts = function(e) { return map(function(s) { return s.text; }, nodeList(e.getElementsByTagName('script'))); }; /** * Evaluate a script. */ ui.evalScript = function(s) { return eval('(function() {\n' + s + '\n})();'); }; /** * Include a script. */ ui.includeScript = function(s) { log('include', s); return eval(s); }; /** * Return true if the client is a mobile device. */ ui.mobiledetected = false; ui.mobile = false; ui.isMobile = function() { if (ui.mobiledetected) return ui.mobile; var ua = navigator.userAgent; if (ua.match(/iPhone/i) || ua.match(/iPad/i) || ua.match(/Android/i) || ua.match(/Blackberry/i) || ua.match(/WebOs/i)) ui.mobile = true; ui.mobiledetected = true; return ui.mobile; }; /** * Convert a host name to a home page title. */ ui.hometitle = function(host) { if (!isNil(window.top.config.hometitle)) return window.top.config.hometitle; var h = reverse(host.split('.')); var d = isNil(cdr(h))? car(h) : cadr(h); return d.substr(0, 1).toUpperCase() + d.substr(1); }; /** * Convert a host name to a window title. */ ui.windowtitle = function(host) { if (!isNil(window.top.config.windowtitle)) return window.top.config.windowtitle; var h = reverse(host.split('.')); var d = isNil(cdr(h))? car(h) : cadr(h); return d.substr(0, 1).toUpperCase() + d.substr(1); }; /** * Convert a CSS position to a numeric position. */ ui.numpos = function(p) { return p == ''? 0 : Number(p.substr(0, p.length - 2)); }; /** * Convert a numeric position to a CSS pixel position. */ ui.pixpos = function(p) { return p + 'px'; }; /** * Reload the current document when orientation changes. */ ui.onorientationchange = function() { window.location.reload(); return true; } /** * Navigate to a new document. */ ui.navigate = function(url, win) { log('navigate', url, win); // Open a new window if (win == '_blank') return window.top.open(url, win); // Open a new document in the current window if (win == '_self') return window.top.open(url, win); // Reload the current window if (win == '_reload') { window.top.location = url; return window.top.location.reload(); } // Let the current top window handle the navigation if (win == '_view') { if (!window.top.onnavigate) return window.top.open(url, '_self'); return window.top.onnavigate(url); } return window.top.open(url, win); } /** * Build a portable tag. */ ui.ahref = function(loc, target, html) { if (target == '_blank') return '' + html + ''; return '' + html + ''; }; /** * Build a menu bar. */ ui.menu = function(name, href, target, hilight) { function Menu() { this.content = function() { if (hilight) return ui.ahref(href, target, '' + name + ''); return ui.ahref(href, target, '' + name + ''); }; } return new Menu(); }; ui.menufunc = function(name, fun, hilight) { function Menu() { this.content = function() { function href(fun, html) { return '' + html + ''; } if (hilight) return href(fun, '' + name + ''); return href(fun, '' + name + ''); }; } return new Menu(); }; ui.menubar = function(left, right) { var bar = '' + '' + '
'; for (i in left) bar = bar + '' bar = bar + '
' + left[i].content() + '
'; for (i in right) bar = bar + '' bar = bar + '
' + right[i].content() + '
'; return bar; }; /** * Convert a list of elements to an HTML table. */ ui.datatable = function(l) { function indent(i) { if (i == 0) return ''; return '  ' + indent(i - 1); } function rows(l, i) { if (isNil(l)) return ''; var e = car(l); // Convert a list of simple values into a list of name value pairs if (!isList(e)) return rows(expandElementValues("'value", l), i); // Convert a list of complex values into a list of name value pairs if (isList(car(e))) return rows(expandElementValues("'value", l), i); // Generate table row for a simple element value if (elementHasValue(e)) { var v = elementValue(e); if (!isList(v)) { return '' + indent(i) + elementName(e).slice(1) + '' + '' + (v != null? v : '') + '' + rows(cdr(l), i); } return rows(expandElementValues(elementName(e), v), i) + rows(cdr(l), i); } // Generate table row for an element with children return '' + indent(i) + elementName(e).slice(1) + '' + '' + '' + rows(elementChildren(e), i + 1) + rows(cdr(l), i); } return '' + rows(l, 0) + '
'; } /** * Convert a list of elements to an HTML single column table. */ ui.datalist = function(l) { function rows(l, i) { if (isNil(l)) return ''; var e = car(l); // Convert a list of simple values into a list of name value pairs if (!isList(e)) return rows(expandElementValues("'value", l), i); // Convert a list of complex values into a list of name value pairs if (isList(car(e))) return rows(expandElementValues("'value", l), i); // Generate table row for a simple element value if (elementHasValue(e)) { var v = elementValue(e); if (!isList(v)) { return '' + (v != null? v : '') + '' + rows(cdr(l), i); } return rows(expandElementValues(elementName(e), v), i) + rows(cdr(l), i); } // Generate rows for an element's children return rows(elementChildren(e), i + 1) + rows(cdr(l), i); } return '' + rows(l, 0) + '
'; } /** * Autocomplete / suggest support for input fields * To use it declare a 'suggest' function as follows: * function suggestItems() { * return new Array('abc', 'def', 'ghi'); * } * then hook it to an input field as follows: * suggest(document.yourForm.yourInputField, suggestItems); */ ui.selectSuggestion = function(node, value) { for (;;) { node = node.parentNode; if (node.tagName.toLowerCase() == 'div') break; } node.selectSuggestion(value); }; ui.hilightSuggestion = function(node, over) { if (over) node.className = 'suggestHilighted'; node.className = 'suggestItem'; }; ui.suggest = function(input, suggestFunction) { input.suggest = suggestFunction; input.selectSuggestion = function(value) { this.hideSuggestDiv(); this.value = value; } input.hideSuggestDiv = function() { if (this.suggestDiv != null) { this.suggestDiv.style.visibility = 'hidden'; } } input.showSuggestDiv = function() { if (this.suggestDiv == null) { this.suggestDiv = document.createElement('div'); this.suggestDiv.input = this; this.suggestDiv.className = 'suggest'; input.parentNode.insertBefore(this.suggestDiv, input); this.suggestDiv.style.visibility = 'hidden'; this.suggestDiv.style.zIndex = '99'; this.suggestDiv.selectSuggestion = function(value) { this.input.selectSuggestion(value); } } var values = this.suggest(); var items = ''; for (var i = 0; i < values.length; i++) { if (values[i].indexOf(this.value) == -1) continue; if (items.length == 0) items += ''; items += ''; } if (items.length != 0) items += '
' + values[i] + '
'; this.suggestDiv.innerHTML = items; if (items.length != 0) { var node = input; var left = 0; var top = 0; for (;;) { left += node.offsetLeft; top += node.offsetTop; node = node.offsetParent; if (node.tagName.toLowerCase() == 'body') break; } this.suggestDiv.style.left = left; this.suggestDiv.style.top = top + input.offsetHeight; this.suggestDiv.style.visibility = 'visible'; } else this.suggestDiv.style.visibility = 'hidden'; } input.onkeydown = function(event) { this.showSuggestDiv(); }; input.onkeyup = function(event) { this.showSuggestDiv(); }; input.onmousedown = function(event) { this.showSuggestDiv(); }; input.onblur = function(event) { setTimeout(function() { input.hideSuggestDiv(); }, 50); }; };