adminerevo/adminer/static/functions.js

767 lines
18 KiB
JavaScript
Raw Normal View History

2013-07-11 01:24:36 +00:00
/** Add or remove CSS class
* @param HTMLElement
* @param string
* @param [bool]
*/
function alterClass(el, className, enable) {
el.className = el.className.replace(RegExp('(^|\\s)' + className + '(\\s|$)'), '$2') + (enable ? ' ' + className : '');
}
/** Toggle visibility
* @param string
* @return boolean
*/
function toggle(id) {
var el = document.getElementById(id);
el.className = (el.className == 'hidden' ? '' : 'hidden');
return true;
}
/** Set permanent cookie
* @param string
* @param number
* @param string optional
*/
function cookie(assign, days) {
var date = new Date();
date.setDate(date.getDate() + days);
document.cookie = assign + '; expires=' + date;
}
/** Verify current Adminer version
* @param string
*/
function verifyVersion(current) {
cookie('adminer_version=0', 1);
var iframe = document.createElement('iframe');
iframe.src = location.protocol + '//www.adminer.org/version/?current=' + current;
iframe.frameBorder = 0;
iframe.marginHeight = 0;
iframe.scrolling = 'no';
iframe.style.width = '7ex';
iframe.style.height = '1.25em';
if (window.postMessage && window.addEventListener) {
iframe.style.display = 'none';
addEventListener('message', function (event) {
if (event.origin == location.protocol + '//www.adminer.org') {
var match = /version=(.+)/.exec(event.data);
if (match) {
cookie('adminer_version=' + match[1], 1);
}
}
}, false);
}
document.getElementById('version').appendChild(iframe);
}
2010-10-16 23:51:56 +00:00
/** Get value of select
2013-07-06 17:31:21 +00:00
* @param HTMLElement <select> or <input>
2010-10-16 23:51:56 +00:00
* @return string
*/
function selectValue(select) {
2013-07-06 17:31:21 +00:00
if (!select.selectedIndex) {
return select.value;
}
2011-02-28 14:57:37 +00:00
var selected = select.options[select.selectedIndex];
return ((selected.attributes.value || {}).specified ? selected.value : selected.text);
2010-10-16 23:51:56 +00:00
}
2013-07-12 21:06:44 +00:00
/** Verify if element has a specified tag name
* @param HTMLElement
* @param string regular expression
* @return bool
*/
function isTag(el, tag) {
var re = new RegExp('^(' + tag + ')$', 'i');
return re.test(el.tagName);
}
/** Get parent node with specified tag name
2012-08-08 16:22:23 +00:00
* @param HTMLElement
2013-04-05 01:15:18 +00:00
* @param string regular expression
2012-08-08 16:22:23 +00:00
* @return HTMLElement
*/
function parentTag(el, tag) {
2013-07-12 21:06:44 +00:00
while (el && !isTag(el, tag)) {
2012-08-08 16:22:23 +00:00
el = el.parentNode;
}
return el;
}
2011-08-11 11:48:27 +00:00
/** Set checked class
* @param HTMLInputElement
*/
function trCheck(el) {
2012-08-08 16:22:23 +00:00
var tr = parentTag(el, 'tr');
2013-07-11 01:24:36 +00:00
alterClass(tr, 'checked', el.checked);
if (el.form && el.form['all']) {
2013-07-08 22:27:53 +00:00
el.form['all'].onclick();
}
}
/** Fill number of selected items
* @param string
2013-07-10 17:12:58 +00:00
* @param string
2013-07-08 22:27:53 +00:00
*/
2013-07-10 17:12:58 +00:00
function selectCount(id, count) {
2013-07-11 23:45:52 +00:00
setHtml(id, (count === '' ? '' : '(' + (count + '').replace(/\B(?=(\d{3})+$)/g, ' ') + ')'));
2013-07-11 23:30:31 +00:00
var inputs = document.getElementById(id).parentNode.parentNode.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
if (input.type == 'submit') {
input.disabled = (count == '0');
}
}
2011-08-11 11:48:27 +00:00
}
/** Check all elements matching given name
* @param HTMLInputElement
* @param RegExp
*/
function formCheck(el, name) {
var elems = el.form.elements;
for (var i=0; i < elems.length; i++) {
if (name.test(elems[i].name)) {
elems[i].checked = el.checked;
2011-08-11 11:48:27 +00:00
trCheck(elems[i]);
}
}
}
/** Check all rows in <table class="checkable">
*/
function tableCheck() {
var tables = document.getElementsByTagName('table');
for (var i=0; i < tables.length; i++) {
if (/(^|\s)checkable(\s|$)/.test(tables[i].className)) {
var trs = tables[i].getElementsByTagName('tr');
for (var j=0; j < trs.length; j++) {
trCheck(trs[j].firstChild.firstChild);
}
}
}
}
/** Uncheck single element
* @param string
*/
function formUncheck(id) {
2011-08-11 11:48:27 +00:00
var el = document.getElementById(id);
el.checked = false;
trCheck(el);
}
/** Get number of checked elements matching given name
* @param HTMLInputElement
* @param RegExp
* @return number
*/
function formChecked(el, name) {
var checked = 0;
var elems = el.form.elements;
for (var i=0; i < elems.length; i++) {
if (name.test(elems[i].name) && elems[i].checked) {
checked++;
}
}
return checked;
}
/** Select clicked row
* @param MouseEvent
2012-10-04 07:42:56 +00:00
* @param [boolean] force click
*/
2012-10-04 07:42:56 +00:00
function tableClick(event, click) {
click = (click || !window.getSelection || getSelection().isCollapsed);
2013-07-19 17:41:06 +00:00
var el = getTarget(event);
2013-07-12 21:06:44 +00:00
while (!isTag(el, 'tr')) {
if (isTag(el, 'table|a|input|textarea')) {
if (el.type != 'checkbox') {
return;
}
checkboxClick(event, el);
2011-08-11 11:48:27 +00:00
click = false;
}
el = el.parentNode;
}
el = el.firstChild.firstChild;
2011-08-11 11:48:27 +00:00
if (click) {
2012-10-04 07:42:56 +00:00
el.checked = !el.checked;
2011-08-11 11:48:27 +00:00
el.onclick && el.onclick();
}
trCheck(el);
}
var lastChecked;
/** Shift-click on checkbox for multiple selection.
* @param MouseEvent
* @param HTMLInputElement
*/
function checkboxClick(event, el) {
if (!el.name) {
return;
}
if (event.shiftKey && (!lastChecked || lastChecked.name == el.name)) {
var checked = (lastChecked ? lastChecked.checked : true);
2012-08-08 16:22:23 +00:00
var inputs = parentTag(el, 'table').getElementsByTagName('input');
var checking = !lastChecked;
for (var i=0; i < inputs.length; i++) {
var input = inputs[i];
if (input.name === el.name) {
if (checking) {
input.checked = checked;
trCheck(input);
}
if (input === el || input === lastChecked) {
if (checking) {
break;
}
checking = true;
}
}
}
} else {
lastChecked = el;
}
}
/** Set HTML code of an element
* @param string
* @param string undefined to set parentNode to &nbsp;
*/
function setHtml(id, html) {
var el = document.getElementById(id);
if (el) {
if (html == undefined) {
el.parentNode.innerHTML = '&nbsp;';
} else {
el.innerHTML = html;
}
}
}
/** Find node position
* @param Node
* @return number
*/
function nodePosition(el) {
var pos = 0;
while (el = el.previousSibling) {
pos++;
}
return pos;
}
2010-11-12 16:31:18 +00:00
/** Go to the specified page
* @param string
* @param string
* @param [MouseEvent]
*/
function pageClick(href, page, event) {
if (!isNaN(page) && page) {
href += (page != 1 ? '&page=' + (page - 1) : '');
2012-04-16 05:18:03 +00:00
location.href = href;
2010-11-12 16:31:18 +00:00
}
}
/** Display items in menu
* @param HTMLElement
* @param MouseEvent
*/
function menuOver(el, event) {
2013-07-19 17:41:06 +00:00
var a = getTarget(event);
2013-07-12 21:06:44 +00:00
if (isTag(a, 'a|span') && a.offsetLeft + a.offsetWidth > a.parentNode.offsetWidth - 15) { // 15 - ellipsis
el.style.overflow = 'visible';
}
}
/** Hide items in menu
* @param HTMLElement
*/
function menuOut(el) {
el.style.overflow = 'auto';
}
/** Add row in select fieldset
* @param HTMLSelectElement
*/
function selectAddRow(field) {
field.onchange = function () {
selectFieldChange(field.form);
};
field.onchange();
2013-05-05 00:02:59 +00:00
var row = cloneNode(field.parentNode);
var selects = row.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) {
2010-10-22 22:02:24 +00:00
selects[i].name = selects[i].name.replace(/[a-z]\[\d+/, '$&1');
selects[i].selectedIndex = 0;
}
var inputs = row.getElementsByTagName('input');
2013-07-06 17:31:21 +00:00
for (var i=0; i < inputs.length; i++) {
inputs[i].name = inputs[i].name.replace(/[a-z]\[\d+/, '$&1');
inputs[i].value = '';
inputs[i].className = '';
}
field.parentNode.parentNode.appendChild(row);
}
/** Prevent onsearch handler on Enter
* @param HTMLInputElement
* @param KeyboardEvent
*/
function selectSearchKeydown(el, event) {
if (event.keyCode == 13 || event.keyCode == 10) {
el.onsearch = function () {
};
}
}
/** Clear column name after resetting search
* @param HTMLInputElement
*/
2013-05-04 01:53:13 +00:00
function selectSearchSearch(el) {
if (!el.value) {
el.parentNode.firstChild.selectedIndex = 0;
}
}
2012-02-29 19:24:01 +00:00
2012-07-29 20:55:39 +00:00
/** Toggles column context menu
* @param HTMLElement
* @param [string] extra class name
*/
function columnMouse(el, className) {
var spans = el.getElementsByTagName('span');
for (var i=0; i < spans.length; i++) {
if (/column/.test(spans[i].className)) {
spans[i].className = 'column' + (className || '');
}
}
}
2012-07-29 18:16:41 +00:00
/** Fill column in search field
* @param string
*/
function selectSearch(name) {
var el = document.getElementById('fieldset-search');
el.className = '';
var divs = el.getElementsByTagName('div');
for (var i=0; i < divs.length; i++) {
var div = divs[i];
2013-07-12 21:06:44 +00:00
if (isTag(div.firstChild, 'select') && selectValue(div.firstChild) == name) {
2012-07-29 18:16:41 +00:00
break;
}
}
if (i == divs.length) {
div.firstChild.value = name;
div.firstChild.onchange();
}
div.lastChild.focus();
}
/** Check if Ctrl key (Command key on Mac) was pressed
* @param KeyboardEvent|MouseEvent
* @return boolean
*/
function isCtrl(event) {
return (event.ctrlKey || event.metaKey) && !event.altKey; // shiftKey allowed
}
2013-07-19 17:41:06 +00:00
/** Return event target
* @param Event
* @return HTMLElement
2013-07-19 17:41:06 +00:00
*/
function getTarget(event) {
return event.target || event.srcElement;
}
2012-07-29 18:16:41 +00:00
2011-05-04 09:42:46 +00:00
/** Send form by Ctrl+Enter on <select> and <textarea>
* @param KeyboardEvent
2011-05-04 09:42:46 +00:00
* @param [string]
* @return boolean
*/
2011-05-04 09:42:46 +00:00
function bodyKeydown(event, button) {
2013-07-19 17:41:06 +00:00
var target = getTarget(event);
2013-07-22 18:45:09 +00:00
if (target.jushTextarea) {
target = target.jushTextarea;
}
2013-07-12 21:06:44 +00:00
if (isCtrl(event) && (event.keyCode == 13 || event.keyCode == 10) && isTag(target, 'select|textarea|input')) { // 13|10 - Enter
target.blur();
2012-04-16 05:18:03 +00:00
if (button) {
target.form[button].click();
} else {
target.form.submit();
}
2013-06-29 19:41:35 +00:00
target.focus();
return false;
}
return true;
}
/** Open form to a new window on Ctrl+click or Shift+click
* @param MouseEvent
*/
function bodyClick(event) {
2013-07-19 17:41:06 +00:00
var target = getTarget(event);
2013-07-12 21:06:44 +00:00
if ((isCtrl(event) || event.shiftKey) && target.type == 'submit' && isTag(target, 'input')) {
target.form.target = '_blank';
setTimeout(function () {
// if (isCtrl(event)) { focus(); } doesn't work
target.form.target = '';
}, 0);
}
}
2010-10-17 05:55:58 +00:00
/** Change focus by Ctrl+Up or Ctrl+Down
* @param KeyboardEvent
* @return boolean
*/
function editingKeydown(event) {
if ((event.keyCode == 40 || event.keyCode == 38) && isCtrl(event)) { // 40 - Down, 38 - Up
2013-07-19 17:41:06 +00:00
var target = getTarget(event);
var sibling = (event.keyCode == 40 ? 'nextSibling' : 'previousSibling');
var el = target.parentNode.parentNode[sibling];
2013-07-12 21:06:44 +00:00
if (el && (isTag(el, 'tr') || (el = el[sibling])) && isTag(el, 'tr') && (el = el.childNodes[nodePosition(target.parentNode)]) && (el = el.childNodes[nodePosition(target)])) {
el.focus();
}
return false;
}
if (event.shiftKey && !bodyKeydown(event, 'insert')) {
eventStop(event);
return false;
}
return true;
}
2011-03-18 08:06:05 +00:00
/** Disable maxlength for functions
* @param HTMLSelectElement
*/
function functionChange(select) {
var input = select.form[select.name.replace(/^function/, 'fields')];
if (selectValue(select)) {
if (input.origType === undefined) {
input.origType = input.type;
2011-03-18 08:06:05 +00:00
input.origMaxLength = input.maxLength;
}
input.removeAttribute('maxlength');
input.type = 'text';
} else if (input.origType) {
input.type = input.origType;
if (input.origMaxLength >= 0) {
input.maxLength = input.origMaxLength;
}
2011-03-18 08:06:05 +00:00
}
helpClose();
2011-03-18 08:06:05 +00:00
}
2013-08-10 00:00:05 +00:00
/** Call this.onchange() if value changes
* @this HTMLInputElement
*/
function keyupChange() {
if (this.value != this.getAttribute('value')) {
this.onchange();
this.setAttribute('value', this.value);
}
}
2010-10-16 23:51:56 +00:00
/** Create AJAX request
* @param string
* @param function (XMLHttpRequest)
2010-10-17 21:54:41 +00:00
* @param [string]
2010-10-16 23:51:56 +00:00
* @return XMLHttpRequest or false in case of an error
*/
function ajax(url, callback, data) {
2012-02-29 19:08:13 +00:00
var request = (window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false));
if (request) {
request.open((data ? 'POST' : 'GET'), url);
if (data) {
2012-02-29 19:08:13 +00:00
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
2010-10-17 05:50:40 +00:00
}
2012-02-29 19:08:13 +00:00
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.onreadystatechange = function () {
if (request.readyState == 4) {
callback(request);
2010-10-16 23:51:56 +00:00
}
2010-10-17 05:19:01 +00:00
};
2012-02-29 19:08:13 +00:00
request.send(data);
2010-10-17 05:19:01 +00:00
}
2012-02-29 19:08:13 +00:00
return request;
2010-10-16 23:51:56 +00:00
}
/** Use setHtml(key, value) for JSON response
* @param string
* @return XMLHttpRequest or false in case of an error
*/
function ajaxSetHtml(url) {
2012-02-29 19:08:13 +00:00
return ajax(url, function (request) {
if (request.status) {
var data = eval('(' + request.responseText + ')');
for (var key in data) {
setHtml(key, data[key]);
}
}
});
}
2013-06-29 19:41:35 +00:00
/** Save form contents through AJAX
* @param HTMLFormElement
* @param string
* @param [HTMLInputElement]
* @return boolean
*/
function ajaxForm(form, message, button) {
var data = [];
var els = form.elements;
for (var i = 0; i < els.length; i++) {
var el = els[i];
if (el.name && !el.disabled) {
if (/^file$/i.test(el.type) && el.value) {
return false;
}
if (!/^(checkbox|radio|submit|file)$/i.test(el.type) || el.checked || el == button) {
2013-07-12 21:06:44 +00:00
data.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(isTag(el, 'select') ? selectValue(el) : el.value));
2013-06-29 19:41:35 +00:00
}
}
}
data = data.join('&');
2013-12-19 20:44:15 +00:00
setHtml('message', '<div class="message">' + message + '</div>');
2013-06-29 19:41:35 +00:00
var url = form.action;
if (!/post/i.test(form.method)) {
url = url.replace(/\?.*/, '') + '?' + data;
data = '';
}
return ajax(url, function (request) {
setHtml('message', request.responseText);
if (window.jush) {
2013-12-19 20:39:03 +00:00
jush.highlight_tag(document.getElementById('message').getElementsByTagName('code'), 0);
2013-06-29 19:41:35 +00:00
}
}, data);
}
/** Display edit field
* @param HTMLElement
* @param MouseEvent
* @param number display textarea instead of input, 2 - load long text
2012-11-01 20:38:03 +00:00
* @param string warning to display
*/
2012-11-01 20:38:03 +00:00
function selectClick(td, event, text, warning) {
2013-07-19 17:41:06 +00:00
var target = getTarget(event);
2013-07-12 21:06:44 +00:00
if (!isCtrl(event) || isTag(td.firstChild, 'input|textarea') || isTag(target, 'a')) {
return;
}
2012-11-01 20:38:03 +00:00
if (warning) {
return alert(warning);
}
var original = td.innerHTML;
2012-08-12 03:21:03 +00:00
text = text || /\n/.test(original);
var input = document.createElement(text ? 'textarea' : 'input');
input.onkeydown = function (event) {
if (!event) {
event = window.event;
}
if (event.keyCode == 27 && !event.shiftKey && !event.altKey && !isCtrl(event)) { // 27 - Esc
inputBlur.apply(input);
td.innerHTML = original;
}
};
var pos = event.rangeOffset;
var value = td.firstChild.alt || td.textContent || td.innerText;
2010-10-17 14:00:29 +00:00
input.style.width = Math.max(td.clientWidth - 14, 20) + 'px'; // 14 = 2 * (td.border + td.padding + input.border)
if (text) {
var rows = 1;
value.replace(/\n/g, function () {
rows++;
});
input.rows = rows;
}
2011-03-21 13:35:58 +00:00
if (value == '\u00A0' || td.getElementsByTagName('i').length) { // &nbsp; or i - NULL
value = '';
}
if (document.selection) {
var range = document.selection.createRange();
range.moveToPoint(event.clientX, event.clientY);
var range2 = range.duplicate();
range2.moveToElementText(td);
range2.setEndPoint('EndToEnd', range);
pos = range2.text.length;
}
td.innerHTML = '';
td.appendChild(input);
2013-05-05 00:02:59 +00:00
setupSubmitHighlight(td);
input.focus();
if (text == 2) { // long text
2012-02-29 19:08:13 +00:00
return ajax(location.href + '&' + encodeURIComponent(td.id) + '=', function (request) {
if (request.status && request.responseText) {
2012-02-29 19:08:13 +00:00
input.value = request.responseText;
input.name = td.id;
}
});
}
2010-11-28 15:40:11 +00:00
input.value = value;
input.name = td.id;
input.selectionStart = pos;
input.selectionEnd = pos;
if (document.selection) {
var range = document.selection.createRange();
range.moveEnd('character', -input.value.length + pos);
range.select();
}
}
2010-11-22 15:52:54 +00:00
2012-08-20 03:32:53 +00:00
/** Load and display next page in select
* @param HTMLLinkElement
* @param number
2013-12-19 20:44:15 +00:00
* @param string
2012-08-20 03:32:53 +00:00
* @return boolean
*/
function selectLoadMore(a, limit, loading) {
var title = a.innerHTML;
var href = a.href;
a.innerHTML = loading;
if (href) {
a.removeAttribute('href');
return ajax(href, function (request) {
var tbody = document.createElement('tbody');
tbody.innerHTML = request.responseText;
document.getElementById('table').appendChild(tbody);
if (tbody.children.length < limit) {
2012-08-20 03:32:53 +00:00
a.parentNode.removeChild(a);
} else {
a.href = href.replace(/\d+$/, function (page) {
return +page + 1;
});
a.innerHTML = title;
}
});
}
}
/** Stop event propagation
* @param Event
*/
function eventStop(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
2013-05-05 00:02:59 +00:00
/** Setup highlighting of default submit button on form field focus
* @param HTMLElement
*/
function setupSubmitHighlight(parent) {
for (var key in { input: 1, select: 1, textarea: 1 }) {
var inputs = parent.getElementsByTagName(key);
for (var i = 0; i < inputs.length; i++) {
setupSubmitHighlightInput(inputs[i])
2013-05-05 00:02:59 +00:00
}
}
}
/** Setup submit highlighting for single element
* @param HTMLElement
*/
function setupSubmitHighlightInput(input) {
if (!/submit|image|file/.test(input.type)) {
addEvent(input, 'focus', inputFocus);
addEvent(input, 'blur', inputBlur);
}
}
2013-05-05 00:02:59 +00:00
/** Highlight default submit button
* @this HTMLInputElement
*/
function inputFocus() {
var submit = findDefaultSubmit(this);
2013-05-05 00:02:59 +00:00
if (submit) {
2013-07-11 01:24:36 +00:00
alterClass(submit, 'default', true);
2013-05-05 00:02:59 +00:00
}
}
/** Unhighlight default submit button
* @this HTMLInputElement
*/
function inputBlur() {
var submit = findDefaultSubmit(this);
2013-05-05 00:02:59 +00:00
if (submit) {
2013-07-11 01:24:36 +00:00
alterClass(submit, 'default');
2013-05-05 00:02:59 +00:00
}
}
/** Find submit button used by Enter
* @param HTMLElement
2013-05-05 00:02:59 +00:00
* @return HTMLInputElement
*/
function findDefaultSubmit(el) {
if (el.jushTextarea) {
el = el.jushTextarea;
}
var inputs = el.form.getElementsByTagName('input');
2013-05-05 00:02:59 +00:00
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
2013-07-10 19:44:03 +00:00
if (input.type == 'submit' && !input.style.zIndex) {
2013-05-05 00:02:59 +00:00
return input;
}
}
}
/** Add event listener
* @param HTMLElement
* @param string without 'on'
* @param function
*/
function addEvent(el, action, handler) {
if (el.addEventListener) {
el.addEventListener(action, handler, false);
} else {
el.attachEvent('on' + action, handler);
}
}
/** Defer focusing element
* @param HTMLElement
*/
function focus(el) {
setTimeout(function () { // this has to be an anonymous function because Firefox passes some arguments to setTimeout callback
el.focus();
}, 0);
}
/** Clone node and setup submit highlighting
* @param HTMLElement
* @return HTMLElement
*/
function cloneNode(el) {
var el2 = el.cloneNode(true);
setupSubmitHighlight(el2);
return el2;
}