/* * 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 = {}; /** * 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) { function Menu(n, h, t) { this.name = n; this.href = h; this.target = isNil(t)? '_parent' : t; this.content = function() { function complete(uri) { var h = uri.indexOf('#'); if (h != -1) return complete(uri.substr(0, h)); var q = uri.indexOf('?'); if (q != -1) return complete(uri.substr(0, q)); if (uri.match('.*\.html$')) return uri; if (uri.match('.*/$')) return uri + 'index.html'; return uri + '/index.html'; } if (complete(this.href) != complete(window.top.location.pathname)) return ui.ahref(this.href, this.target, '' + this.name + ''); return ui.ahref(this.href, this.target, '' + this.name + ''); }; } return new Menu(name, href, target); }; 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; }; /** * 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); }; }; /** * Return a child element of a node with the given id. */ ui.elementByID = function(node, id) { 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) { if (!isNil(document.widget)) return document.widget; return document; } return ui.elementByID($(document), id); }; /** * Return a dictionary of the query parameters. */ ui.queryParams = function() { var qp = new Array(); var qs = window.location.search.substring(1).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 the fragment parameters. */ ui.fragmentParams = function() { var qp = new Array(); var qs = window.location.hash.substring(1).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 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; }; /** * Initialize a document's body. */ ui.pagetransitions = false; ui.initbody = function() { if (ui.isMobile()) { //log('init', window.location); // Position the main body div off screen if (ui.pagetransitions) { var bdiv = $('bodydiv'); if (!isNil(bdiv)) { bdiv.className = 'bodydivloading'; } } // Install orientation handler document.body.onorientationchange = ui.onorientationchange; } return true; } /** * Reload the current document when orientation changes. */ ui.onorientationchange = function() { window.open(window.location, '_self'); return true; } /** * Post process a document after it's loaded. */ ui.onload = function() { // Save the current page location in local storage // (except for login and logout pages) var path = document.location.pathname; if (path.indexOf('/login/') != 0 && path.indexOf('/logout/') != 0) localStorage.setItem('ui.lastvisited', '' + document.location); // Make the document body visible //log('visible', $('bodydiv').className); document.body.style.visibility = 'visible'; if (ui.pagetransitions && ui.isMobile()) { //log('onload', window.location); // Slide the main body div in setTimeout(function() { var bdiv = $('bodydiv'); if (!isNil(bdiv)) { function transitionend(e) { bdiv.removeEventListener('webkitTransitionEnd', transitionend, false); bdiv.removeEventListener('transitionend', transitionend, false); bdiv.className = 'bodydiv'; //log('loadtransitionend', window.location); }; bdiv.addEventListener('webkitTransitionEnd', transitionend, false); bdiv.addEventListener('transitionend', transitionend, false); //log('loadtransitionstart', window.location); bdiv.className = 'bodydivloaded'; } }, 0); } return true; }; /** * Navigate to a new document. */ ui.navigate = function(url, win) { function opendoc(url, win) { if (win == '_reload') { window.location = url; return window.location.reload(); } return window.open(url, win); } if (ui.pagetransitions && ui.isMobile() && win != '_blank') { // Slide the main body div out, then open the new document var bdiv = $('bodydiv'); if (!isNil(bdiv)) { function transitionend(e) { bdiv.removeEventListener('webkitTransitionEnd', transitionend, false); bdiv.removeEventListener('transitionend', transitionend, false); //log('navigatetransitionend', window.location); return opendoc(url, win); }; bdiv.addEventListener('webkitTransitionEnd', transitionend, false); bdiv.addEventListener('transitionend', transitionend, false); //log('navigatetransitionstart', window.location); bdiv.className = 'bodydivunloaded'; return true; } } return opendoc(url, win); } /** * Pre process a document just before it's unloaded. */ ui.onbeforeunload = function() { if (ui.pagetransitions && ui.isMobile()) { // Slide the main body div out var bdiv = $('bodydiv'); if (!isNil(bdiv)) bdiv.className = 'bodydivunloaded'; } }; /** * Return the last visited page. */ ui.lastvisited = function() { return localStorage.getItem('ui.lastvisited'); } /** * 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'; }; /** * 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) + '
'; }