adminerevo/adminer/static/functions.js

540 lines
14 KiB
JavaScript
Raw Normal View History

/** 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
*/
2011-02-15 17:11:24 +00:00
function verifyVersion() {
cookie('adminer_version=0', 1);
var script = document.createElement('script');
2011-02-15 17:11:24 +00:00
script.src = location.protocol + '//www.adminer.org/version.php';
document.body.appendChild(script);
}
2010-10-16 23:51:56 +00:00
/** Get value of select
* @param HTMLSelectElement
* @return string
*/
function selectValue(select) {
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
}
2011-08-11 11:48:27 +00:00
/** Set checked class
* @param HTMLInputElement
*/
function trCheck(el) {
var tr = el.parentNode.parentNode;
tr.className = tr.className.replace(/(^|\s)checked(\s|$)/, '$2') + (el.checked ? ' checked' : '');
}
/** 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
*/
function tableClick(event) {
2011-08-11 11:48:27 +00:00
var click = true;
var el = event.target || event.srcElement;
while (!/^tr$/i.test(el.tagName)) {
2011-08-11 11:48:27 +00:00
if (/^table$/i.test(el.tagName)) {
return;
}
2011-08-11 11:48:27 +00:00
if (/^(a|input|textarea)$/i.test(el.tagName)) {
click = false;
}
el = el.parentNode;
}
el = el.firstChild.firstChild;
2011-08-11 11:48:27 +00:00
if (click) {
el.click && el.click();
el.onclick && el.onclick();
}
trCheck(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) : '');
2011-03-16 12:08:46 +00:00
if (!ajaxSend(href)) {
2010-11-12 16:31:18 +00:00
location.href = href;
}
}
}
/** Add row in select fieldset
* @param HTMLSelectElement
*/
function selectAddRow(field) {
field.onchange = function () { };
var row = field.parentNode.cloneNode(true);
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');
if (inputs.length) {
2010-10-22 22:02:24 +00:00
inputs[0].name = inputs[0].name.replace(/[a-z]\[\d+/, '$&1');
inputs[0].value = '';
inputs[0].className = '';
}
field.parentNode.parentNode.appendChild(row);
}
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) {
var target = event.target || event.srcElement;
2011-10-10 07:13:05 +00:00
if (event.keyCode == 27 && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) { // 27 - Esc
ajaxXmlhttp.aborted = true;
if (ajaxXmlhttp.abort) {
ajaxXmlhttp.abort();
}
2012-02-29 19:02:34 +00:00
document.body.className = document.body.className.replace(/ loading/g, '');
2011-10-10 07:13:05 +00:00
onblur = function () { };
if (originalFavicon) {
replaceFavicon(originalFavicon);
}
}
2011-05-04 09:42:46 +00:00
if (event.ctrlKey && (event.keyCode == 13 || event.keyCode == 10) && !event.altKey && !event.metaKey && /select|textarea|input/i.test(target.tagName)) { // 13|10 - Enter, shiftKey allowed
target.blur();
if (!ajaxForm(target.form, (button ? button + '=1' : ''))) {
if (button) {
target.form[button].click();
} else {
target.form.submit();
}
}
return false;
}
return true;
}
2010-10-17 05:55:58 +00:00
/** Change focus by Ctrl+Up or Ctrl+Down
* @param KeyboardEvent
* @return boolean
*/
function editingKeydown(event) {
2011-03-18 08:12:31 +00:00
if ((event.keyCode == 40 || event.keyCode == 38) && event.ctrlKey && !event.altKey && !event.metaKey) { // 40 - Down, 38 - Up, shiftKey allowed
var target = event.target || event.srcElement;
var sibling = (event.keyCode == 40 ? 'nextSibling' : 'previousSibling');
var el = target.parentNode.parentNode[sibling];
if (el && (/^tr$/i.test(el.tagName) || (el = el[sibling])) && /^tr$/i.test(el.tagName) && (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.origMaxLength === undefined) {
input.origMaxLength = input.maxLength;
}
input.removeAttribute('maxlength');
} else if (input.origMaxLength >= 0) {
input.maxLength = input.origMaxLength;
}
}
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) {
2010-10-17 05:19:01 +00:00
var xmlhttp = (window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false));
if (xmlhttp) {
xmlhttp.open((data ? 'POST' : 'GET'), url);
if (data) {
2010-10-17 05:50:40 +00:00
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
2010-10-17 05:19:01 +00:00
xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
2011-01-03 15:42:08 +00:00
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
callback(xmlhttp);
2010-10-16 23:51:56 +00:00
}
2010-10-17 05:19:01 +00:00
};
2010-10-17 05:50:40 +00:00
xmlhttp.send(data);
2010-10-17 05:19:01 +00:00
}
2010-10-16 23:51:56 +00:00
return xmlhttp;
}
/** Use setHtml(key, value) for JSON response
* @param string
* @return XMLHttpRequest or false in case of an error
*/
function ajaxSetHtml(url) {
return ajax(url, function (xmlhttp) {
if (xmlhttp.status) {
var data = eval('(' + xmlhttp.responseText + ')');
for (var key in data) {
setHtml(key, data[key]);
}
}
});
}
2011-07-19 12:44:43 +00:00
var originalFavicon;
2011-04-03 15:17:26 +00:00
2011-03-11 22:21:54 +00:00
/** Replace favicon
* @param string
*/
function replaceFavicon(href) {
var favicon = document.getElementById('favicon');
2011-04-03 15:17:26 +00:00
if (favicon) {
favicon.href = href;
favicon.parentNode.appendChild(favicon); // to replace the icon in Firefox
}
2011-03-11 22:21:54 +00:00
}
2011-03-11 15:47:37 +00:00
var ajaxState = 0;
2011-10-10 07:13:05 +00:00
var ajaxXmlhttp = {};
2010-11-18 11:17:06 +00:00
/** Safely load content to #content
* @param string
* @param [string]
2011-03-11 15:47:37 +00:00
* @param [boolean]
2011-06-08 09:23:08 +00:00
* @param [boolean]
* @return XMLHttpRequest or false in case of an error
*/
2011-06-08 09:23:08 +00:00
function ajaxSend(url, data, popState, noscroll) {
2011-03-16 12:08:46 +00:00
if (!history.pushState) {
return false;
}
2011-10-10 07:13:05 +00:00
ajaxXmlhttp.aborted = true;
if (ajaxXmlhttp.abort) {
ajaxXmlhttp.abort();
}
var currentState = ++ajaxState;
onblur = function () {
2011-07-19 12:44:43 +00:00
if (!originalFavicon) {
originalFavicon = (document.getElementById('favicon') || {}).href;
}
replaceFavicon(document.getElementById('loader').firstChild.src);
};
document.body.className += ' loading';
2011-10-10 07:13:05 +00:00
ajaxXmlhttp = ajax(url, function (xmlhttp) {
if (!xmlhttp.aborted && currentState == ajaxState) {
var title = xmlhttp.getResponseHeader('X-AJAX-Title');
if (title) {
document.title = decodeURIComponent(title);
}
var redirect = xmlhttp.getResponseHeader('X-AJAX-Redirect');
if (redirect) {
2011-03-16 12:08:46 +00:00
return ajaxSend(redirect, '', popState);
}
onblur = function () { };
2011-08-12 16:06:45 +00:00
if (originalFavicon) {
replaceFavicon(originalFavicon);
}
if (!popState) {
if (data || url != location.href) {
history.pushState(data, '', url); //! remember window position
2010-11-23 10:50:53 +00:00
}
}
if (!noscroll && !/&order/.test(url)) {
scrollTo(0, 0);
}
setHtml('content', (xmlhttp.status ? xmlhttp.responseText : '<p class="error">' + noResponse));
2012-02-29 19:02:34 +00:00
document.body.className = document.body.className.replace(/ loading/g, '');
var content = document.getElementById('content');
var scripts = content.getElementsByTagName('script');
var length = scripts.length; // required to avoid infinite loop
for (var i=0; i < length; i++) {
var script = document.createElement('script');
script.text = scripts[i].text;
content.appendChild(script);
}
var as = document.getElementById('menu').getElementsByTagName('a');
var href = location.href.replace(/(&(sql=|dump=|(select|table)=[^&]*)).*/, '$1');
for (var i=0; i < as.length; i++) {
as[i].className = (href == as[i].href ? 'active' : '');
}
var dump = document.getElementById('dump');
if (dump) {
var match = /&(select|table)=([^&]+)/.exec(href);
dump.href = dump.href.replace(/[^=]+$/, '') + (match ? match[2] : '');
}
//! modify Change database hidden fields
if (window.jush) {
jush.highlight_tag('code', 0);
}
}
}, data);
2011-10-10 07:13:05 +00:00
return ajaxXmlhttp;
}
/** Revive page from history
2011-03-11 23:20:27 +00:00
* @param PopStateEvent|history
*/
onpopstate = function (event) {
2011-04-25 19:06:42 +00:00
if ((ajaxState || event.state) && !/#/.test(location.href)) {
ajaxSend(location.href, (event.state && confirm(areYouSure) ? event.state : ''), 1); // 1 - disable pushState
2011-03-24 07:24:57 +00:00
} else {
ajaxState++;
2011-03-16 12:07:44 +00:00
}
2011-04-25 19:06:42 +00:00
};
2010-10-16 23:51:56 +00:00
/** Send form by AJAX GET
* @param HTMLFormElement
2010-10-17 21:54:41 +00:00
* @param [string]
2011-06-08 09:23:08 +00:00
* @param [boolean]
2010-10-16 23:51:56 +00:00
* @return XMLHttpRequest or false in case of an error
*/
2011-06-08 09:23:08 +00:00
function ajaxForm(form, data, noscroll) {
2011-06-13 14:23:51 +00:00
if ((/&(database|scheme|create|view|sql|user|dump|call)=/.test(location.href) && !/\./.test(data)) || (form.onsubmit && form.onsubmit() === false)) { // . - type="image"
return false;
}
2010-10-16 23:51:56 +00:00
var params = [ ];
for (var i=0; i < form.elements.length; i++) {
var el = form.elements[i];
if (/file/i.test(el.type) && el.value) {
return false;
} else if (el.name && (!/checkbox|radio|submit|file/i.test(el.type) || el.checked)) {
2010-10-17 05:50:40 +00:00
params.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(/select/i.test(el.tagName) ? selectValue(el) : el.value));
2010-10-16 23:51:56 +00:00
}
}
2010-10-17 21:54:41 +00:00
if (data) {
params.push(data);
}
2010-10-17 05:50:40 +00:00
if (form.method == 'post') {
return ajaxSend((/\?/.test(form.action) ? form.action : location.href), params.join('&'), false, noscroll); // ? - always part of Adminer URL
2010-10-17 05:50:40 +00:00
}
return ajaxSend((form.action || location.href).replace(/\?.*/, '') + '?' + params.join('&'), '', false, noscroll);
2010-10-16 23:51:56 +00:00
}
/** Display edit field
* @param HTMLElement
* @param MouseEvent
* @param number display textarea instead of input, 2 - load long text
*/
function selectDblClick(td, event, text) {
if (/input|textarea/i.test(td.firstChild.tagName)) {
return;
}
var original = td.innerHTML;
var input = document.createElement(text ? 'textarea' : 'input');
input.onkeydown = function (event) {
if (!event) {
event = window.event;
}
if (event.keyCode == 27 && !(event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)) { // 27 - Esc
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);
input.focus();
if (text == 2) { // long text
return ajax(location.href + '&' + encodeURIComponent(td.id) + '=', function (xmlhttp) {
if (xmlhttp.status) {
input.value = xmlhttp.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
/** Load link by AJAX
* @param MouseEvent
2010-11-26 09:26:08 +00:00
* @param string
2010-11-28 16:58:35 +00:00
* @param string
2011-08-11 11:48:47 +00:00
* @return boolean
2010-11-22 15:52:54 +00:00
*/
2010-11-28 16:58:35 +00:00
function bodyClick(event, db, ns) {
if (event.button || event.shiftKey || event.altKey || event.metaKey) {
2010-12-06 00:13:03 +00:00
return;
}
if (event.getPreventDefault ? event.getPreventDefault() : event.returnValue === false || event.defaultPrevented) {
2010-11-23 10:50:53 +00:00
return false;
}
2010-11-22 15:52:54 +00:00
var el = event.target || event.srcElement;
if (/^a$/i.test(el.parentNode.tagName)) {
el = el.parentNode;
}
if (/^a$/i.test(el.tagName) && !/:|#|&download=/i.test(el.getAttribute('href')) && /[&?]username=/.test(el.href) && !event.ctrlKey) {
2010-11-22 15:52:54 +00:00
var match = /&db=([^&]*)/.exec(el.href);
2010-11-28 16:58:35 +00:00
var match2 = /&ns=([^&]*)/.exec(el.href);
return !(db == (match ? decodeURIComponent(match[1]) : '') && ns == (match2 ? decodeURIComponent(match2[1]) : '') && ajaxSend(el.href));
2010-11-22 15:52:54 +00:00
}
if (/^input$/i.test(el.tagName) && /image|submit/.test(el.type)) {
if (event.ctrlKey) {
el.form.target = '_blank';
} else {
return !ajaxForm(el.form, (el.name ? encodeURIComponent(el.name) + (el.type == 'image' ? '.x' : '') + '=1' : ''), el.type == 'image');
}
2010-11-23 10:50:53 +00:00
}
return true;
2010-11-22 15:52:54 +00:00
}
/** Stop event propagation
* @param Event
*/
function eventStop(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}