Merge pull request #1153 from niphlod/fix/1100

fixes #1100
This commit is contained in:
mdipierro
2016-01-04 09:41:43 -06:00
3 changed files with 2220 additions and 2142 deletions
+224 -198
View File
@@ -1,4 +1,4 @@
(function($, undefined) { (function ($, undefined) {
/* /*
* Unobtrusive scripting adapter for jQuery, largely taken from * Unobtrusive scripting adapter for jQuery, largely taken from
* the wonderful https://github.com/rails/jquery-ujs * the wonderful https://github.com/rails/jquery-ujs
@@ -7,68 +7,72 @@
* Released under the MIT license * Released under the MIT license
* *
*/ */
if($.web2py !== undefined) { 'use strict';
if ($.web2py !== undefined) {
$.error('web2py.js has already been loaded!'); $.error('web2py.js has already been loaded!');
} }
String.prototype.reverse = function () {
String.prototype.reverse = function() {
return this.split('').reverse().join(''); return this.split('').reverse().join('');
}; };
var web2py; var web2py;
$.web2py = web2py = { $.web2py = web2py = {
popup: function(url) { isUndefined: function (obj) {
/* grabbed from underscore.js */
return obj === void 0;
},
popup: function (url) {
/* popup a window */ /* popup a window */
newwindow = window.open(url, 'name', 'height=400,width=600'); var newwindow = window.open(url, 'name', 'height=400,width=600');
if(window.focus) newwindow.focus(); if (window.focus) newwindow.focus();
return false; return false;
}, },
collapse: function(id) { collapse: function (id) {
/* toggle an element */ /* toggle an element */
$('#' + id).slideToggle(); $('#' + id).slideToggle();
}, },
fade: function(id, value) { fade: function (id, value) {
/*fade something*/ /*fade something*/
if(value > 0) $('#' + id).hide().fadeIn('slow'); if (value > 0) $('#' + id).hide().fadeIn('slow');
else $('#' + id).show().fadeOut('slow'); else $('#' + id).show().fadeOut('slow');
}, },
ajax: function(u, s, t) { ajax: function (u, s, t) {
/*simple ajax function*/ /*simple ajax function*/
query = ''; var query = '';
if(typeof s == "string") { if (typeof s == 'string') {
d = $(s).serialize(); var d = $(s).serialize();
if(d) { if (d) {
query = d; query = d;
} }
} else { } else {
pcs = []; var pcs = [];
if(s != null && s != undefined) if (s !== null && !web2py.isUndefined(s))
for(i = 0; i < s.length; i++) { for (var i = 0; i < s.length; i++) {
q = $("[name=" + s[i] + "]").serialize(); var q = $('[name=' + s[i] + ']').serialize();
if(q) { if (q) {
pcs.push(q); pcs.push(q);
} }
} }
if(pcs.length > 0) { if (pcs.length > 0) {
query = pcs.join("&"); query = pcs.join('&');
} }
} }
$.ajax({ $.ajax({
type: "POST", type: 'POST',
url: u, url: u,
data: query, data: query,
success: function(msg) { success: function (msg) {
if(t) { if (t) {
if(t == ':eval') eval(msg); if (t == ':eval') eval(msg);
else if(typeof t == 'string') $("#" + t).html(msg); else if (typeof t == 'string') $('#' + t).html(msg);
else t(msg); else t(msg);
} }
} }
}); });
}, },
ajax_fields: function(target) { ajax_fields: function (target) {
/* /*
*this attaches something to a newly loaded fragment/page *this attaches something to a newly loaded fragment/page
* Ideally all events should be bound to the document, so we can avoid calling * Ideally all events should be bound to the document, so we can avoid calling
@@ -76,29 +80,31 @@
*/ */
/*adds btn class to buttons*/ /*adds btn class to buttons*/
$('button:not([class^="btn"])', target).addClass('btn'); $('button:not([class^="btn"])', target).addClass('btn');
$('form input[type="submit"]:not([class^="btn"]), form input[type="button"]:not([class^="btn"])', target).addClass('btn'); $(
'form input[type="submit"]:not([class^="btn"]), form input[type="button"]:not([class^="btn"])',
target).addClass('btn');
/* javascript for PasswordWidget*/ /* javascript for PasswordWidget*/
$('input[type=password][data-w2p_entropy]', target).each(function() { $('input[type=password][data-w2p_entropy]', target).each(function () {
web2py.validate_entropy($(this)); web2py.validate_entropy($(this));
}); });
/* javascript for ListWidget*/ /* javascript for ListWidget*/
$('ul.w2p_list', target).each(function() { $('ul.w2p_list', target).each(function () {
function pe(ul, e) { function pe(ul, e) {
var new_line = ml(ul); var new_line = ml(ul);
rel(ul); rel(ul);
if($(e.target).parent().is(':visible')) { if ($(e.target).parent().is(':visible')) {
/* make sure we didn't delete the element before we insert after */ /* make sure we didn't delete the element before we insert after */
new_line.insertAfter($(e.target).parent()); new_line.insertAfter($(e.target).parent());
} else { } else {
/* the line we clicked on was deleted, just add to end of list */ /* the line we clicked on was deleted, just add to end of list */
new_line.appendTo(ul); new_line.appendTo(ul);
} }
new_line.find(":text").focus(); new_line.find(':text').focus();
return false; return false;
} }
function rl(ul, e) { function rl(ul, e) {
if($(ul).children().length > 1) { if ($(ul).children().length > 1) {
/* only remove if we have more than 1 item so the list is never empty */ /* only remove if we have more than 1 item so the list is never empty */
$(e.target).parent().remove(); $(e.target).parent().remove();
} }
@@ -106,32 +112,33 @@
function ml(ul) { function ml(ul) {
/* clone the first field */ /* clone the first field */
var line = $(ul).find("li:first").clone(true); var line = $(ul).find('li:first').clone(true);
line.find(':text').val(''); line.find(':text').val('');
return line; return line;
} }
function rel(ul) { function rel(ul) {
/* keep only as many as needed*/ /* keep only as many as needed*/
$(ul).find("li").each(function() { $(ul).find('li').each(function () {
var trimmed = $.trim($(this.firstChild).val()); var trimmed = $.trim($(this.firstChild).val());
if(trimmed == '') $(this).remove(); if (trimmed === '') $(this).remove();
else $(this.firstChild).val(trimmed); else $(this.firstChild).val(trimmed);
}); });
} }
var ul = this; var ul = this;
$(ul).find(":text").after('<a href="#">+</a>&nbsp;<a href="#">-</a>').keypress(function(e) { $(ul).find(':text').after('<a href="#">+</a>&nbsp;<a href="#">-</a>').keypress(
return(e.which == 13) ? pe(ul, e) : true; function (e) {
}).next().click(function(e) { return (e.which == 13) ? pe(ul, e) : true;
}).next().click(function (e) {
pe(ul, e); pe(ul, e);
e.preventDefault(); e.preventDefault();
}).next().click(function(e) { }).next().click(function (e) {
rl(ul, e); rl(ul, e);
e.preventDefault(); e.preventDefault();
}); });
}); });
}, },
ajax_init: function(target) { ajax_init: function (target) {
/*called whenever a fragment gets loaded */ /*called whenever a fragment gets loaded */
$('.w2p_hidden', target).hide(); $('.w2p_hidden', target).hide();
web2py.manage_errors(target); web2py.manage_errors(target);
@@ -140,68 +147,71 @@
web2py.component_handler(target); web2py.component_handler(target);
}, },
/* manage errors in forms */ /* manage errors in forms */
manage_errors: function(target) { manage_errors: function (target) {
$('div.error', target).hide().slideDown('slow'); $('div.error', target).hide().slideDown('slow');
}, },
after_ajax: function(xhr) { after_ajax: function (xhr) {
/* called whenever an ajax request completes */ /* called whenever an ajax request completes */
var command = xhr.getResponseHeader('web2py-component-command'); var command = xhr.getResponseHeader('web2py-component-command');
var flash = xhr.getResponseHeader('web2py-component-flash'); var flash = xhr.getResponseHeader('web2py-component-flash');
if(command !== null) { if (command !== null) {
eval(decodeURIComponent(command)); eval(decodeURIComponent(command));
} }
if(flash) { if (flash) {
web2py.flash(decodeURIComponent(flash)) web2py.flash(decodeURIComponent(flash));
} }
}, },
event_handlers: function() { event_handlers: function () {
/* /*
* This is called once for page * This is called once for page
* Ideally it should bound all the things that are needed * Ideally it should bound all the things that are needed
* and require no dom manipulations * and require no dom manipulations
*/ */
var doc = $(document); var doc = $(document);
doc.on('click', '.w2p_flash', function(e) { doc.on('click', '.w2p_flash', function () {
var t = $(this); var t = $(this);
if(t.css('top') == '0px') t.slideUp('slow'); if (t.css('top') == '0px') t.slideUp('slow');
else t.fadeOut(); else t.fadeOut();
}); });
doc.on('keyup', 'input.integer', function() { doc.on('keyup', 'input.integer', function () {
var nvalue = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse(); var nvalue = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
if(this.value != nvalue) this.value = nvalue; if (this.value != nvalue) this.value = nvalue;
}); });
doc.on('keyup', 'input.double, input.decimal', function() { doc.on('keyup', 'input.double, input.decimal', function () {
var nvalue = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse(); var nvalue = this.value.reverse().replace(
if(this.value != nvalue) this.value = nvalue; /[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
if (this.value != nvalue) this.value = nvalue;
}); });
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?"; var confirm_message = !web2py.isUndefined(w2p_ajax_confirm_message) ? w2p_ajax_confirm_message :
doc.on('click', "input[type='checkbox'].delete", function() { 'Are you sure you want to delete this object?';
if(this.checked) doc.on('click', 'input[type="checkbox"].delete', function () {
if(!web2py.confirm(confirm_message)) this.checked = false; if (this.checked)
if (!web2py.confirm(confirm_message)) this.checked = false;
}); });
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S"; var datetime_format = !web2py.isUndefined(w2p_ajax_datetime_format) ? w2p_ajax_datetime_format :
doc.on('click', "input.datetime", function() { '%Y-%m-%d %H:%M:%S';
doc.on('click', 'input.datetime', function () {
var tformat = $(this).data('w2p_datetime_format'); var tformat = $(this).data('w2p_datetime_format');
var active = $(this).data('w2p_datetime'); var active = $(this).data('w2p_datetime');
var format = (typeof tformat != 'undefined') ? tformat : datetime_format; var format = !web2py.isUndefined(tformat) ? tformat : datetime_format;
if(active === undefined) { if (active === undefined) {
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: format, ifFormat: format,
showsTime: true, showsTime: true,
timeFormat: "24" timeFormat: '24'
}); });
$(this).attr('autocomplete', 'off'); $(this).attr('autocomplete', 'off');
$(this).data('w2p_datetime', 1); $(this).data('w2p_datetime', 1);
$(this).trigger('click'); $(this).trigger('click');
} }
}); });
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d"; var date_format = !web2py.isUndefined(w2p_ajax_date_format) ? w2p_ajax_date_format : '%Y-%m-%d';
doc.on('click', "input.date", function() { doc.on('click', 'input.date', function () {
var tformat = $(this).data('w2p_date_format'); var tformat = $(this).data('w2p_date_format');
var active = $(this).data('w2p_date'); var active = $(this).data('w2p_date');
var format = (typeof tformat != 'undefined') ? tformat : date_format; var format = !web2py.isUndefined(tformat) ? tformat : date_format;
if(active === undefined) { if (active === undefined) {
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: format, ifFormat: format,
@@ -212,9 +222,9 @@
$(this).trigger('click'); $(this).trigger('click');
} }
}); });
doc.on('focus', "input.time", function() { doc.on('focus', 'input.time', function () {
var active = $(this).data('w2p_time'); var active = $(this).data('w2p_time');
if(active === undefined) { if (web2py.isUndefined(active)) {
$(this).timeEntry({ $(this).timeEntry({
spinnerImage: '' spinnerImage: ''
}).attr('autocomplete', 'off'); }).attr('autocomplete', 'off');
@@ -222,94 +232,99 @@
} }
}); });
/* help preventing double form submission for normal form (not LOADed) */ /* help preventing double form submission for normal form (not LOADed) */
$(doc).on('submit', 'form', function() { $(doc).on('submit', 'form', function () {
var submit_button = $(this).find(web2py.formInputClickSelector); var submit_button = $(this).find(web2py.formInputClickSelector);
web2py.disableElement(submit_button); web2py.disableElement(submit_button);
/* safeguard in case the form doesn't trigger a refresh,
see https://github.com/web2py/web2py/issues/1100 */
setTimeout(function () {
web2py.enableElement(submit_button);
}, 5000);
}); });
doc.ajaxSuccess(function(e, xhr) { doc.ajaxSuccess(function (e, xhr) {
var redirect = xhr.getResponseHeader('web2py-redirect-location'); var redirect = xhr.getResponseHeader('web2py-redirect-location');
if(redirect !== null) { if (redirect !== null) {
window.location = redirect; window.location = redirect;
}; }
/* run this here only if this Ajax request is NOT for a web2py component. */ /* run this here only if this Ajax request is NOT for a web2py component. */
if(xhr.getResponseHeader('web2py-component-content') == null) { if (xhr.getResponseHeader('web2py-component-content') === null) {
web2py.after_ajax(xhr); web2py.after_ajax(xhr);
}; }
}); });
doc.ajaxError(function(e, xhr, settings, exception) { doc.ajaxError(function (e, xhr, settings, exception) {
/*personally I don't like it. /*personally I don't like it.
*if there's an error it it flashed and can be removed *if there's an error it it flashed and can be removed
*as any other message *as any other message
*doc.off('click', '.w2p_flash') *doc.off('click', '.w2p_flash')
*/ */
switch(xhr.status) { switch (xhr.status) {
case 500: case 500:
web2py.flash(ajax_error_500); web2py.flash(ajax_error_500);
} }
}); });
}, },
trap_form: function(action, target) { trap_form: function (action, target) {
/* traps any LOADed form */ /* traps any LOADed form */
$('#' + target + ' form').each(function(i) { $('#' + target + ' form').each(function () {
var form = $(this); var form = $(this);
if(form.hasClass('no_trap')) { if (form.hasClass('no_trap')) {
return; return;
} }
var w2p_target = $(this).attr('data-w2p_target'); var w2p_target = $(this).attr('data-w2p_target');
if (typeof w2p_target === typeof undefined || w2p_target === false) { if (web2py.isUndefined(w2p_target) || w2p_target === false) {
form.attr('data-w2p_target', target); form.attr('data-w2p_target', target);
} else { } else {
target = w2p_target; target = w2p_target;
} }
var url = form.attr('action'); var url = form.attr('action');
if((url === "") || (url === "#") || (typeof url === 'undefined')) { if ((url === '') || (url === '#') || web2py.isUndefined(url)) {
/* form has no action. Use component url. */ /* form has no action. Use component url. */
url = action; url = action;
} }
form.submit(function(e) { form.submit(function (e) {
web2py.disableElement(form.find(web2py.formInputClickSelector)); web2py.disableElement(form.find(web2py.formInputClickSelector));
web2py.hide_flash(); web2py.hide_flash();
web2py.ajax_page('post', url, form.serialize(), target, form); web2py.ajax_page('post', url, form.serialize(), target, form);
e.preventDefault(); e.preventDefault();
}); });
form.on('click', web2py.formInputClickSelector, function(e) { form.on('click', web2py.formInputClickSelector, function (e) {
e.preventDefault(); e.preventDefault();
var input_name = $(this).attr('name'); var input_name = $(this).attr('name');
if(input_name != undefined) { if (!web2py.isUndefined(input_name)) {
$('<input type="hidden" />').attr('name', input_name) $('<input type="hidden" />').attr('name', input_name)
.attr('value', $(this).val()).appendTo(form) .attr('value', $(this).val()).appendTo(form);
} }
form.trigger('submit'); form.trigger('submit');
}); });
}); });
}, },
ajax_page: function(method, action, data, target, element) { ajax_page: function (method, action, data, target, element) {
/* element is a new parameter, but should be put be put in front */ /* element is a new parameter, but should be put be put in front */
if(element == undefined) element = $(document); if (web2py.isUndefined(element)) element = $(document);
/* if target is not there, fill it with something that there isn't in the page*/ /* if target is not there, fill it with something that there isn't in the page*/
if(target == undefined || target == '') target = 'w2p_none'; if (web2py.isUndefined(target) || target === '') target = 'w2p_none';
if(web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */ if (web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */
$.ajax({ $.ajax({
'type': method, 'type': method,
'url': action, 'url': action,
'data': data, 'data': data,
'beforeSend': function(xhr, settings) { 'beforeSend': function (xhr, settings) {
xhr.setRequestHeader('web2py-component-location', document.location); xhr.setRequestHeader('web2py-component-location', document.location);
xhr.setRequestHeader('web2py-component-element', target); xhr.setRequestHeader('web2py-component-element', target);
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
}, },
'success': function(data, status, xhr) { 'success': function (data, status, xhr) {
/*bummer for form submissions....the element is not there after complete /*bummer for form submissions....the element is not there after complete
*because it gets replaced by the new response.... *because it gets replaced by the new response....
*/ */
web2py.fire(element, 'ajax:success', [data, status, xhr], target); web2py.fire(element, 'ajax:success', [data, status, xhr], target);
}, },
'error': function(xhr, status, error) { 'error': function (xhr, status, error) {
/*bummer for form submissions....in addition to the element being not there after /*bummer for form submissions....in addition to the element being not there after
*complete because it gets replaced by the new response, standard form *complete because it gets replaced by the new response, standard form
*handling just returns the same status code for good and bad *handling just returns the same status code for good and bad
@@ -317,7 +332,7 @@
*/ */
web2py.fire(element, 'ajax:error', [xhr, status, error], target); web2py.fire(element, 'ajax:error', [xhr, status, error], target);
}, },
'complete': function(xhr, status) { 'complete': function (xhr, status) {
web2py.fire(element, 'ajax:complete', [xhr, status], target); web2py.fire(element, 'ajax:complete', [xhr, status], target);
web2py.updatePage(xhr, target); /* Parse and load the html received */ web2py.updatePage(xhr, target); /* Parse and load the html received */
web2py.trap_form(action, target); web2py.trap_form(action, target);
@@ -327,33 +342,33 @@
}); });
} }
}, },
component: function(action, target, timeout, times, el) { component: function (action, target, timeout, times, el) {
/* element is a new parameter, but should be put in front */ /* element is a new parameter, but should be put in front */
$(function() { $(function () {
var jelement = $("#" + target); var jelement = $('#' + target);
var element = jelement.get(0); var element = jelement.get(0);
var statement = "jQuery('#" + target + "').get(0).reload();"; var statement = 'jQuery("#' + target + '").get(0).reload();';
element.reload = function() { element.reload = function () {
/* Continue if times is Infinity or /* Continue if times is Infinity or
* the times limit is not reached * the times limit is not reached
*/ */
if(element.reload_check()) { if (element.reload_check()) {
web2py.ajax_page('get', action, null, target, el); web2py.ajax_page('get', action, null, target, el);
} }
}; };
/* Method to check timing limit */ /* Method to check timing limit */
element.reload_check = function() { element.reload_check = function () {
if(jelement.hasClass('w2p_component_stop')) { if (jelement.hasClass('w2p_component_stop')) {
clearInterval(this.timing); clearInterval(this.timing);
return false; return false;
} }
if(this.reload_counter == Infinity) { if (this.reload_counter == Infinity) {
return true; return true;
} else { } else {
if(!isNaN(this.reload_counter)) { if (!isNaN(this.reload_counter)) {
this.reload_counter -= 1; this.reload_counter -= 1;
if(this.reload_counter < 0) { if (this.reload_counter < 0) {
if(!this.run_once) { if (!this.run_once) {
clearInterval(this.timing); clearInterval(this.timing);
return false; return false;
} }
@@ -364,10 +379,10 @@
} }
return false; return false;
}; };
if(!isNaN(timeout)) { if (!isNaN(timeout)) {
element.timeout = timeout; element.timeout = timeout;
element.reload_counter = times; element.reload_counter = times;
if(times > 1) { if (times > 1) {
/* Multiple or infinite reload /* Multiple or infinite reload
* Run first iteration * Run first iteration
*/ */
@@ -375,7 +390,7 @@
element.run_once = false; element.run_once = false;
element.timing = setInterval(statement, timeout); element.timing = setInterval(statement, timeout);
element.reload_counter -= 1; element.reload_counter -= 1;
} else if(times == 1) { } else if (times == 1) {
/* Run once with timeout */ /* Run once with timeout */
element.run_once = true; element.run_once = true;
element.setTimeout = setTimeout; element.setTimeout = setTimeout;
@@ -388,21 +403,21 @@
} }
}); });
}, },
updatePage: function(xhr, target) { updatePage: function (xhr, target) {
var t = $('#' + target); var t = $('#' + target);
var html = $.parseHTML(xhr.responseText, document, true); var html = $.parseHTML(xhr.responseText, document, true);
var title_elements = $(html).filter('title').add($(html).find('title')); var title_elements = $(html).filter('title').add($(html).find('title'));
var title = title_elements.last().text(); var title = title_elements.last().text();
if(title) { if (title) {
title_elements.remove(); /* Remove any title elements from the response */ title_elements.remove(); /* Remove any title elements from the response */
document.title = $.trim(title); /* Set the new document title */ document.title = $.trim(title); /* Set the new document title */
} }
var content = xhr.getResponseHeader('web2py-component-content'); var content = xhr.getResponseHeader('web2py-component-content');
if(content == 'prepend') t.prepend(xhr.responseText); if (content == 'prepend') t.prepend(xhr.responseText);
else if(content == 'append') t.append(xhr.responseText); else if (content == 'append') t.append(xhr.responseText);
else if(content != 'hide') t.html(html); else if (content != 'hide') t.html(html);
}, },
calc_entropy: function(mystring) { calc_entropy: function (mystring) {
/* calculate a simple entropy for a given string */ /* calculate a simple entropy for a given string */
var csets = new Array( var csets = new Array(
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
@@ -413,41 +428,41 @@
seen = {}, seen = {},
lastset = null, lastset = null,
mystringlist = mystring.split(''); mystringlist = mystring.split('');
for(var i = 0; i < mystringlist.length; i++) { /* classify this character */ for (var i = 0; i < mystringlist.length; i++) { /* classify this character */
var c = mystringlist[i], var c = mystringlist[i],
inset = 5; inset = 5;
for(var j = 0; j < csets.length; j++) for (var j = 0; j < csets.length; j++)
if(csets[j].indexOf(c) != -1) { if (csets[j].indexOf(c) != -1) {
inset = j; inset = j;
break; break;
} }
/*calculate effect of character on alphabet size */ /*calculate effect of character on alphabet size */
if(!(inset in seen)) { if (!(inset in seen)) {
seen[inset] = 1; seen[inset] = 1;
score += csets[inset].length; score += csets[inset].length;
} else if(!(c in other)) { } else if (!(c in other)) {
score += 1; score += 1;
other[c] = 1; other[c] = 1;
} }
if(inset != lastset) { if (inset != lastset) {
score += 1; score += 1;
lastset = inset; lastset = inset;
} }
} }
var entropy = mystring.length * Math.log(score) / 0.6931471805599453; var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
return Math.round(entropy * 100) / 100 return Math.round(entropy * 100) / 100;
}, },
validate_entropy: function(myfield, req_entropy) { validate_entropy: function (myfield, req_entropy) {
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy'); if (!web2py.isUndefined(myfield.data('w2p_entropy'))) req_entropy = myfield.data('w2p_entropy');
var validator = function() { var validator = function () {
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy; var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
var r = 0, var r = 0,
g = 0, g = 0,
b = 0, b = 0,
rs = function(x) { rs = function (x) {
return Math.round(x * 15).toString(16) return Math.round(x * 15).toString(16);
}; };
if(v <= 0.5) { if (v <= 0.5) {
r = 1.0; r = 1.0;
g = 2.0 * v; g = 2.0 * v;
} else { } else {
@@ -456,17 +471,18 @@
} }
var color = '#' + rs(r) + rs(g) + rs(b); var color = '#' + rs(r) + rs(g) + rs(b);
myfield.css('background-color', color); myfield.css('background-color', color);
entropy_callback = myfield.data('entropy_callback'); var entropy_callback = myfield.data('entropy_callback');
if(entropy_callback) entropy_callback(v); if (entropy_callback) entropy_callback(v);
} };
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check'); if (!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator)
.addClass('entropy_check');
}, },
web2py_websocket: function(url, onmessage, onopen, onclose) { web2py_websocket: function (url, onmessage, onopen, onclose) {
if("WebSocket" in window) { if ('WebSocket' in window) {
var ws = new WebSocket(url); var ws = new WebSocket(url);
ws.onopen = onopen ? onopen : (function() {}); ws.onopen = onopen ? onopen : (function () {});
ws.onmessage = onmessage; ws.onmessage = onmessage;
ws.onclose = onclose ? onclose : (function() {}); ws.onclose = onclose ? onclose : (function () {});
return true; /* supported */ return true; /* supported */
} else return false; /* not supported */ } else return false; /* not supported */
}, },
@@ -478,7 +494,7 @@
/* Form input elements re-enabled after form submission */ /* Form input elements re-enabled after form submission */
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled', enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
/* Triggers an event on an element and returns false if the event result is false */ /* Triggers an event on an element and returns false if the event result is false */
fire: function(obj, type, data, target) { fire: function (obj, type, data, target) {
var event = $.Event(type, { var event = $.Event(type, {
'containerTarget': $('#' + target)[0] 'containerTarget': $('#' + target)[0]
}); });
@@ -486,45 +502,50 @@
return event.result !== false; return event.result !== false;
}, },
/* Helper function, needed to provide consistent behavior in IE */ /* Helper function, needed to provide consistent behavior in IE */
stopEverything: function(e) { stopEverything: function (e) {
$(e.target).trigger('w2p:everythingStopped'); $(e.target).trigger('w2p:everythingStopped');
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}, },
confirm: function(message) { confirm: function (message) {
return confirm(message); return confirm(message);
}, },
/* replace element's html with the 'data-disable-with' after storing original html /* replace element's html with the 'data-disable-with' after storing original html
* and prevent clicking on it */ * and prevent clicking on it */
disableElement: function(el) { disableElement: function (el) {
if (!web2py.isUndefined(el.data('w2p_disable'))) {
return false;
}
el.addClass('disabled'); el.addClass('disabled');
var method = el.is('input') ? 'val' : 'html'; var method = el.is('input') ? 'val' : 'html';
//method = el.attr('name') ? 'html' : 'val'; //method = el.attr('name') ? 'html' : 'val';
var disable_with_message = (typeof w2p_ajax_disable_with_message != 'undefined') ? w2p_ajax_disable_with_message : "Working..."; var disable_with_message = (!web2py.isUndefined(w2p_ajax_disable_with_message)) ?
w2p_ajax_disable_with_message : 'Working...';
/*store enabled state if not already disabled */ /*store enabled state if not already disabled */
if(el.data('w2p_enable_with') === undefined) { if (web2py.isUndefined(el.data('w2p_enable_with'))) {
el.data('w2p_enable_with', el[method]()); el.data('w2p_enable_with', el[method]());
} }
/*if you don't want to see "working..." on buttons, replace the following /*if you don't want to see "working..." on buttons, replace the following
* two lines with this one * two lines with this one
* el.data('w2p_disable_with', el[method]()); * el.data('w2p_disable_with', el[method]());
*/ */
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) { if ((el.data('w2p_disable_with') == 'default') || (web2py.isUndefined(el.data(
'w2p_disable_with')))) {
el.data('w2p_disable_with', disable_with_message); el.data('w2p_disable_with', disable_with_message);
} }
/* set to disabled state*/ /* set to disabled state*/
el[method](el.data('w2p_disable_with')); el[method](el.data('w2p_disable_with'));
el.bind('click.w2pDisable', function(e) { /* prevent further clicking*/ el.bind('click.w2pDisable', function (e) { /* prevent further clicking*/
return web2py.stopEverything(e); return web2py.stopEverything(e);
}); });
}, },
/* restore element to its original state which was disabled by 'disableElement' above*/ /* restore element to its original state which was disabled by 'disableElement' above*/
enableElement: function(el) { enableElement: function (el) {
var method = el.is('input') ? 'val' : 'html'; var method = el.is('input') ? 'val' : 'html';
if(el.data('w2p_enable_with') !== undefined) { if (!web2py.isUndefined(el.data('w2p_enable_with'))) {
/* set to old enabled state */ /* set to old enabled state */
el[method](el.data('w2p_enable_with')); el[method](el.data('w2p_enable_with'));
el.removeData('w2p_enable_with'); el.removeData('w2p_enable_with');
@@ -533,47 +554,47 @@
el.unbind('click.w2pDisable'); el.unbind('click.w2pDisable');
}, },
/*convenience wrapper, internal use only */ /*convenience wrapper, internal use only */
simple_component: function(action, target, element) { simple_component: function (action, target, element) {
web2py.component(action, target, 0, 1, element); web2py.component(action, target, 0, 1, element);
}, },
/*helper for flash messages*/ /*helper for flash messages*/
flash: function(message, status) { flash: function (message, status) {
var flash = $('.w2p_flash'); var flash = $('.w2p_flash');
web2py.hide_flash(); web2py.hide_flash();
flash.html(message).addClass(status); flash.html(message).addClass(status);
if(flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown(); if (flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown();
}, },
hide_flash: function() { hide_flash: function () {
$('.w2p_flash').fadeOut(0).html(''); $('.w2p_flash').fadeOut(0).html('');
}, },
show_if_handler: function(target) { show_if_handler: function (target) {
var triggers = {}; var triggers = {};
var show_if = function() { var show_if = function () {
var t = $(this); var t = $(this);
var id = t.attr('id'); var id = t.attr('id');
t.attr('value', t.val()); t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) { for (var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target); var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target); var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown(); if (t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide(); else tr.hide();
} }
}; };
$('[data-show-trigger]', target).each(function() { $('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger'); var name = $(this).attr('data-show-trigger');
// The field exists only when creating/editing a row // The field exists only when creating/editing a row
if($('#' + name).length) { if ($('#' + name).length) {
if(!triggers[name]) triggers[name] = []; if (!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id')); triggers[name].push($(this).attr('id'));
} }
}); });
for(var name in triggers) { for (var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if); $('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target)); show_if.call($('#' + name, target));
}; }
}, },
component_handler: function(target) { component_handler: function (target) {
$('div[data-w2p_remote]', target).each(function() { $('div[data-w2p_remote]', target).each(function () {
var remote, times, timeout, target; var remote, times, timeout, target;
var el = $(this); var el = $(this);
remote = el.data('w2p_remote'); remote = el.data('w2p_remote');
@@ -581,9 +602,9 @@
timeout = el.data('w2p_timeout'); timeout = el.data('w2p_timeout');
target = el.attr('id'); target = el.attr('id');
web2py.component(remote, target, timeout, times, $(this)); web2py.component(remote, target, timeout, times, $(this));
}) });
}, },
a_handler: function(el, e) { a_handler: function (el, e) {
e.preventDefault(); e.preventDefault();
var method = el.data('w2p_method'); var method = el.data('w2p_method');
var action = el.attr('href'); var action = el.attr('href');
@@ -591,55 +612,56 @@
var confirm_message = el.data('w2p_confirm'); var confirm_message = el.data('w2p_confirm');
var pre_call = el.data('w2p_pre_call'); var pre_call = el.data('w2p_pre_call');
if(pre_call != undefined) { if (!web2py.isUndefined(pre_call)) {
eval(pre_call); eval(pre_call);
} }
if(confirm_message) { if (confirm_message) {
if(confirm_message == 'default') if (confirm_message == 'default') {
confirm_message = w2p_ajax_confirm_message || confirm_message = w2p_ajax_confirm_message ||
'Are you sure you want to delete this object?'; 'Are you sure you want to delete this object?';
if(!web2py.confirm(confirm_message)) { }
if (!web2py.confirm(confirm_message)) {
web2py.stopEverything(e); web2py.stopEverything(e);
return; return;
} }
} }
if(target == undefined) { if (web2py.isUndefined(target)) {
if(method == 'GET') { if (method == 'GET') {
web2py.ajax_page('get', action, [], '', el); web2py.ajax_page('get', action, [], '', el);
} else if(method == 'POST') { } else if (method == 'POST') {
web2py.ajax_page('post', action, [], '', el); web2py.ajax_page('post', action, [], '', el);
} }
} else { } else {
if(method == 'GET') { if (method == 'GET') {
web2py.ajax_page('get', action, [], target, el); web2py.ajax_page('get', action, [], target, el);
} else if(method == 'POST') { } else if (method == 'POST') {
web2py.ajax_page('post', action, [], target, el); web2py.ajax_page('post', action, [], target, el);
} }
} }
}, },
a_handlers: function() { a_handlers: function () {
var el = $(document); var el = $(document);
el.on('click', 'a[data-w2p_method]', function(e) { el.on('click', 'a[data-w2p_method]', function (e) {
web2py.a_handler($(this), e); web2py.a_handler($(this), e);
}); });
/* removal of element should happen only on success */ /* removal of element should happen only on success */
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function(e) { el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function () {
var el = $(this); var el = $(this);
var toremove = el.data('w2p_remove'); var toremove = el.data('w2p_remove');
if(toremove != undefined) { if (!web2py.isUndefined(toremove)) {
toremove = el.closest(toremove); toremove = el.closest(toremove);
if(!toremove.length) { if (!toremove.length) {
/*this enables removal of whatever selector if a closest is not found */ /*this enables removal of whatever selector if a closest is not found */
toremove = $(toremove); toremove = $(toremove);
} }
toremove.remove(); toremove.remove();
} }
}); });
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function(e) { el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function () {
web2py.disableElement($(this)); web2py.disableElement($(this));
}); });
/*re-enable click on completion*/ /*re-enable click on completion*/
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function(e) { el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function () {
web2py.enableElement($(this)); web2py.enableElement($(this));
}); });
}, },
@@ -648,15 +670,19 @@
- Replaces element text with value of 'data-disable-with' attribute - Replaces element text with value of 'data-disable-with' attribute
- Sets disabled property to true - Sets disabled property to true
*/ */
disableFormElements: function(form) { disableFormElements: function (form) {
form.find(web2py.disableSelector).each(function() { form.find(web2py.disableSelector).each(function () {
var element = $(this), var element = $(this),
method = element.is('button') ? 'html' : 'val'; method = element.is('button') ? 'html' : 'val';
var disable_with = element.data('w2p_disable_with'); var disable_with = element.data('w2p_disable_with');
if(disable_with == undefined) { var disable = element.data('w2p_disable');
element.data('w2p_disable_with', element[method]()) if (!web2py.isUndefined(disable)) {
return false;
} }
if(element.data('w2p_enable_with') === undefined) { if (web2py.isUndefined(disable_with)) {
element.data('w2p_disable_with', element[method]());
}
if (web2py.isUndefined(element.data('w2p_enable_with'))) {
element.data('w2p_enable_with', element[method]()); element.data('w2p_enable_with', element[method]());
} }
element[method](element.data('w2p_disable_with')); element[method](element.data('w2p_disable_with'));
@@ -668,50 +694,50 @@
- Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`) - Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`)
- Sets disabled property to false - Sets disabled property to false
*/ */
enableFormElements: function(form) { enableFormElements: function (form) {
form.find(web2py.enableSelector).each(function() { form.find(web2py.enableSelector).each(function () {
var element = $(this), var element = $(this),
method = element.is('button') ? 'html' : 'val'; method = element.is('button') ? 'html' : 'val';
if(element.data('w2p_enable_with')) { if (element.data('w2p_enable_with')) {
element[method](element.data('w2p_enable_with')); element[method](element.data('w2p_enable_with'));
element.removeData('w2p_enable_with'); element.removeData('w2p_enable_with');
} }
element.prop('disabled', false); element.prop('disabled', false);
}); });
}, },
form_handlers: function() { form_handlers: function () {
var el = $(document); var el = $(document);
el.on('ajax:beforeSend', 'form[data-w2p_target]', function(e) { el.on('ajax:beforeSend', 'form[data-w2p_target]', function () {
web2py.disableFormElements($(this)); web2py.disableFormElements($(this));
}); });
el.on('ajax:complete', 'form[data-w2p_target]', function(e) { el.on('ajax:complete', 'form[data-w2p_target]', function () {
web2py.enableFormElements($(this)); web2py.enableFormElements($(this));
}); });
}, },
/* Invalidate and force reload of a web2py component /* Invalidate and force reload of a web2py component
*/ */
invalidate: function(target) { invalidate: function (target) {
$('div[data-w2p_remote]', target).each(function() { $('div[data-w2p_remote]', target).each(function () {
var el = $('#' + $(this).attr('id')).get(0); var el = $('#' + $(this).attr('id')).get(0);
if(el.timing !== undefined) { // Block triggering regular routines if (!web2py.isUndefined(el.timing)) { // Block triggering regular routines
clearInterval(el.timing); clearInterval(el.timing);
} }
}); });
$.web2py.component_handler(target); $.web2py.component_handler(target);
}, },
main_hook: function() { main_hook: function () {
var flash = $('.w2p_flash'); var flash = $('.w2p_flash');
flash.hide(); flash.hide();
if(flash.html()) web2py.flash(flash.html()); if (flash.html()) web2py.flash(flash.html());
web2py.ajax_init(document); web2py.ajax_init(document);
web2py.event_handlers(); web2py.event_handlers();
web2py.a_handlers(); web2py.a_handlers();
web2py.form_handlers(); web2py.form_handlers();
} }
} };
/*end of functions */ /*end of functions */
/*main hook*/ /*main hook*/
$(function() { $(function () {
web2py.main_hook(); web2py.main_hook();
}); });
+224 -198
View File
@@ -1,4 +1,4 @@
(function($, undefined) { (function ($, undefined) {
/* /*
* Unobtrusive scripting adapter for jQuery, largely taken from * Unobtrusive scripting adapter for jQuery, largely taken from
* the wonderful https://github.com/rails/jquery-ujs * the wonderful https://github.com/rails/jquery-ujs
@@ -7,68 +7,72 @@
* Released under the MIT license * Released under the MIT license
* *
*/ */
if($.web2py !== undefined) { 'use strict';
if ($.web2py !== undefined) {
$.error('web2py.js has already been loaded!'); $.error('web2py.js has already been loaded!');
} }
String.prototype.reverse = function () {
String.prototype.reverse = function() {
return this.split('').reverse().join(''); return this.split('').reverse().join('');
}; };
var web2py; var web2py;
$.web2py = web2py = { $.web2py = web2py = {
popup: function(url) { isUndefined: function (obj) {
/* grabbed from underscore.js */
return obj === void 0;
},
popup: function (url) {
/* popup a window */ /* popup a window */
newwindow = window.open(url, 'name', 'height=400,width=600'); var newwindow = window.open(url, 'name', 'height=400,width=600');
if(window.focus) newwindow.focus(); if (window.focus) newwindow.focus();
return false; return false;
}, },
collapse: function(id) { collapse: function (id) {
/* toggle an element */ /* toggle an element */
$('#' + id).slideToggle(); $('#' + id).slideToggle();
}, },
fade: function(id, value) { fade: function (id, value) {
/*fade something*/ /*fade something*/
if(value > 0) $('#' + id).hide().fadeIn('slow'); if (value > 0) $('#' + id).hide().fadeIn('slow');
else $('#' + id).show().fadeOut('slow'); else $('#' + id).show().fadeOut('slow');
}, },
ajax: function(u, s, t) { ajax: function (u, s, t) {
/*simple ajax function*/ /*simple ajax function*/
query = ''; var query = '';
if(typeof s == "string") { if (typeof s == 'string') {
d = $(s).serialize(); var d = $(s).serialize();
if(d) { if (d) {
query = d; query = d;
} }
} else { } else {
pcs = []; var pcs = [];
if(s != null && s != undefined) if (s !== null && !web2py.isUndefined(s))
for(i = 0; i < s.length; i++) { for (var i = 0; i < s.length; i++) {
q = $("[name=" + s[i] + "]").serialize(); var q = $('[name=' + s[i] + ']').serialize();
if(q) { if (q) {
pcs.push(q); pcs.push(q);
} }
} }
if(pcs.length > 0) { if (pcs.length > 0) {
query = pcs.join("&"); query = pcs.join('&');
} }
} }
$.ajax({ $.ajax({
type: "POST", type: 'POST',
url: u, url: u,
data: query, data: query,
success: function(msg) { success: function (msg) {
if(t) { if (t) {
if(t == ':eval') eval(msg); if (t == ':eval') eval(msg);
else if(typeof t == 'string') $("#" + t).html(msg); else if (typeof t == 'string') $('#' + t).html(msg);
else t(msg); else t(msg);
} }
} }
}); });
}, },
ajax_fields: function(target) { ajax_fields: function (target) {
/* /*
*this attaches something to a newly loaded fragment/page *this attaches something to a newly loaded fragment/page
* Ideally all events should be bound to the document, so we can avoid calling * Ideally all events should be bound to the document, so we can avoid calling
@@ -76,29 +80,31 @@
*/ */
/*adds btn class to buttons*/ /*adds btn class to buttons*/
$('button:not([class^="btn"])', target).addClass('btn'); $('button:not([class^="btn"])', target).addClass('btn');
$('form input[type="submit"]:not([class^="btn"]), form input[type="button"]:not([class^="btn"])', target).addClass('btn'); $(
'form input[type="submit"]:not([class^="btn"]), form input[type="button"]:not([class^="btn"])',
target).addClass('btn');
/* javascript for PasswordWidget*/ /* javascript for PasswordWidget*/
$('input[type=password][data-w2p_entropy]', target).each(function() { $('input[type=password][data-w2p_entropy]', target).each(function () {
web2py.validate_entropy($(this)); web2py.validate_entropy($(this));
}); });
/* javascript for ListWidget*/ /* javascript for ListWidget*/
$('ul.w2p_list', target).each(function() { $('ul.w2p_list', target).each(function () {
function pe(ul, e) { function pe(ul, e) {
var new_line = ml(ul); var new_line = ml(ul);
rel(ul); rel(ul);
if($(e.target).parent().is(':visible')) { if ($(e.target).parent().is(':visible')) {
/* make sure we didn't delete the element before we insert after */ /* make sure we didn't delete the element before we insert after */
new_line.insertAfter($(e.target).parent()); new_line.insertAfter($(e.target).parent());
} else { } else {
/* the line we clicked on was deleted, just add to end of list */ /* the line we clicked on was deleted, just add to end of list */
new_line.appendTo(ul); new_line.appendTo(ul);
} }
new_line.find(":text").focus(); new_line.find(':text').focus();
return false; return false;
} }
function rl(ul, e) { function rl(ul, e) {
if($(ul).children().length > 1) { if ($(ul).children().length > 1) {
/* only remove if we have more than 1 item so the list is never empty */ /* only remove if we have more than 1 item so the list is never empty */
$(e.target).parent().remove(); $(e.target).parent().remove();
} }
@@ -106,32 +112,33 @@
function ml(ul) { function ml(ul) {
/* clone the first field */ /* clone the first field */
var line = $(ul).find("li:first").clone(true); var line = $(ul).find('li:first').clone(true);
line.find(':text').val(''); line.find(':text').val('');
return line; return line;
} }
function rel(ul) { function rel(ul) {
/* keep only as many as needed*/ /* keep only as many as needed*/
$(ul).find("li").each(function() { $(ul).find('li').each(function () {
var trimmed = $.trim($(this.firstChild).val()); var trimmed = $.trim($(this.firstChild).val());
if(trimmed == '') $(this).remove(); if (trimmed === '') $(this).remove();
else $(this.firstChild).val(trimmed); else $(this.firstChild).val(trimmed);
}); });
} }
var ul = this; var ul = this;
$(ul).find(":text").after('<a href="#">+</a>&nbsp;<a href="#">-</a>').keypress(function(e) { $(ul).find(':text').after('<a href="#">+</a>&nbsp;<a href="#">-</a>').keypress(
return(e.which == 13) ? pe(ul, e) : true; function (e) {
}).next().click(function(e) { return (e.which == 13) ? pe(ul, e) : true;
}).next().click(function (e) {
pe(ul, e); pe(ul, e);
e.preventDefault(); e.preventDefault();
}).next().click(function(e) { }).next().click(function (e) {
rl(ul, e); rl(ul, e);
e.preventDefault(); e.preventDefault();
}); });
}); });
}, },
ajax_init: function(target) { ajax_init: function (target) {
/*called whenever a fragment gets loaded */ /*called whenever a fragment gets loaded */
$('.w2p_hidden', target).hide(); $('.w2p_hidden', target).hide();
web2py.manage_errors(target); web2py.manage_errors(target);
@@ -140,68 +147,71 @@
web2py.component_handler(target); web2py.component_handler(target);
}, },
/* manage errors in forms */ /* manage errors in forms */
manage_errors: function(target) { manage_errors: function (target) {
$('div.error', target).hide().slideDown('slow'); $('div.error', target).hide().slideDown('slow');
}, },
after_ajax: function(xhr) { after_ajax: function (xhr) {
/* called whenever an ajax request completes */ /* called whenever an ajax request completes */
var command = xhr.getResponseHeader('web2py-component-command'); var command = xhr.getResponseHeader('web2py-component-command');
var flash = xhr.getResponseHeader('web2py-component-flash'); var flash = xhr.getResponseHeader('web2py-component-flash');
if(command !== null) { if (command !== null) {
eval(decodeURIComponent(command)); eval(decodeURIComponent(command));
} }
if(flash) { if (flash) {
web2py.flash(decodeURIComponent(flash)) web2py.flash(decodeURIComponent(flash));
} }
}, },
event_handlers: function() { event_handlers: function () {
/* /*
* This is called once for page * This is called once for page
* Ideally it should bound all the things that are needed * Ideally it should bound all the things that are needed
* and require no dom manipulations * and require no dom manipulations
*/ */
var doc = $(document); var doc = $(document);
doc.on('click', '.w2p_flash', function(e) { doc.on('click', '.w2p_flash', function () {
var t = $(this); var t = $(this);
if(t.css('top') == '0px') t.slideUp('slow'); if (t.css('top') == '0px') t.slideUp('slow');
else t.fadeOut(); else t.fadeOut();
}); });
doc.on('keyup', 'input.integer', function() { doc.on('keyup', 'input.integer', function () {
var nvalue = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse(); var nvalue = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
if(this.value != nvalue) this.value = nvalue; if (this.value != nvalue) this.value = nvalue;
}); });
doc.on('keyup', 'input.double, input.decimal', function() { doc.on('keyup', 'input.double, input.decimal', function () {
var nvalue = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse(); var nvalue = this.value.reverse().replace(
if(this.value != nvalue) this.value = nvalue; /[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
if (this.value != nvalue) this.value = nvalue;
}); });
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?"; var confirm_message = !web2py.isUndefined(w2p_ajax_confirm_message) ? w2p_ajax_confirm_message :
doc.on('click', "input[type='checkbox'].delete", function() { 'Are you sure you want to delete this object?';
if(this.checked) doc.on('click', 'input[type="checkbox"].delete', function () {
if(!web2py.confirm(confirm_message)) this.checked = false; if (this.checked)
if (!web2py.confirm(confirm_message)) this.checked = false;
}); });
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S"; var datetime_format = !web2py.isUndefined(w2p_ajax_datetime_format) ? w2p_ajax_datetime_format :
doc.on('click', "input.datetime", function() { '%Y-%m-%d %H:%M:%S';
doc.on('click', 'input.datetime', function () {
var tformat = $(this).data('w2p_datetime_format'); var tformat = $(this).data('w2p_datetime_format');
var active = $(this).data('w2p_datetime'); var active = $(this).data('w2p_datetime');
var format = (typeof tformat != 'undefined') ? tformat : datetime_format; var format = !web2py.isUndefined(tformat) ? tformat : datetime_format;
if(active === undefined) { if (active === undefined) {
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: format, ifFormat: format,
showsTime: true, showsTime: true,
timeFormat: "24" timeFormat: '24'
}); });
$(this).attr('autocomplete', 'off'); $(this).attr('autocomplete', 'off');
$(this).data('w2p_datetime', 1); $(this).data('w2p_datetime', 1);
$(this).trigger('click'); $(this).trigger('click');
} }
}); });
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d"; var date_format = !web2py.isUndefined(w2p_ajax_date_format) ? w2p_ajax_date_format : '%Y-%m-%d';
doc.on('click', "input.date", function() { doc.on('click', 'input.date', function () {
var tformat = $(this).data('w2p_date_format'); var tformat = $(this).data('w2p_date_format');
var active = $(this).data('w2p_date'); var active = $(this).data('w2p_date');
var format = (typeof tformat != 'undefined') ? tformat : date_format; var format = !web2py.isUndefined(tformat) ? tformat : date_format;
if(active === undefined) { if (active === undefined) {
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: format, ifFormat: format,
@@ -212,9 +222,9 @@
$(this).trigger('click'); $(this).trigger('click');
} }
}); });
doc.on('focus', "input.time", function() { doc.on('focus', 'input.time', function () {
var active = $(this).data('w2p_time'); var active = $(this).data('w2p_time');
if(active === undefined) { if (web2py.isUndefined(active)) {
$(this).timeEntry({ $(this).timeEntry({
spinnerImage: '' spinnerImage: ''
}).attr('autocomplete', 'off'); }).attr('autocomplete', 'off');
@@ -222,94 +232,99 @@
} }
}); });
/* help preventing double form submission for normal form (not LOADed) */ /* help preventing double form submission for normal form (not LOADed) */
$(doc).on('submit', 'form', function() { $(doc).on('submit', 'form', function () {
var submit_button = $(this).find(web2py.formInputClickSelector); var submit_button = $(this).find(web2py.formInputClickSelector);
web2py.disableElement(submit_button); web2py.disableElement(submit_button);
/* safeguard in case the form doesn't trigger a refresh,
see https://github.com/web2py/web2py/issues/1100 */
setTimeout(function () {
web2py.enableElement(submit_button);
}, 5000);
}); });
doc.ajaxSuccess(function(e, xhr) { doc.ajaxSuccess(function (e, xhr) {
var redirect = xhr.getResponseHeader('web2py-redirect-location'); var redirect = xhr.getResponseHeader('web2py-redirect-location');
if(redirect !== null) { if (redirect !== null) {
window.location = redirect; window.location = redirect;
}; }
/* run this here only if this Ajax request is NOT for a web2py component. */ /* run this here only if this Ajax request is NOT for a web2py component. */
if(xhr.getResponseHeader('web2py-component-content') == null) { if (xhr.getResponseHeader('web2py-component-content') === null) {
web2py.after_ajax(xhr); web2py.after_ajax(xhr);
}; }
}); });
doc.ajaxError(function(e, xhr, settings, exception) { doc.ajaxError(function (e, xhr, settings, exception) {
/*personally I don't like it. /*personally I don't like it.
*if there's an error it it flashed and can be removed *if there's an error it it flashed and can be removed
*as any other message *as any other message
*doc.off('click', '.w2p_flash') *doc.off('click', '.w2p_flash')
*/ */
switch(xhr.status) { switch (xhr.status) {
case 500: case 500:
web2py.flash(ajax_error_500); web2py.flash(ajax_error_500);
} }
}); });
}, },
trap_form: function(action, target) { trap_form: function (action, target) {
/* traps any LOADed form */ /* traps any LOADed form */
$('#' + target + ' form').each(function(i) { $('#' + target + ' form').each(function () {
var form = $(this); var form = $(this);
if(form.hasClass('no_trap')) { if (form.hasClass('no_trap')) {
return; return;
} }
var w2p_target = $(this).attr('data-w2p_target'); var w2p_target = $(this).attr('data-w2p_target');
if (typeof w2p_target === typeof undefined || w2p_target === false) { if (web2py.isUndefined(w2p_target) || w2p_target === false) {
form.attr('data-w2p_target', target); form.attr('data-w2p_target', target);
} else { } else {
target = w2p_target; target = w2p_target;
} }
var url = form.attr('action'); var url = form.attr('action');
if((url === "") || (url === "#") || (typeof url === 'undefined')) { if ((url === '') || (url === '#') || web2py.isUndefined(url)) {
/* form has no action. Use component url. */ /* form has no action. Use component url. */
url = action; url = action;
} }
form.submit(function(e) { form.submit(function (e) {
web2py.disableElement(form.find(web2py.formInputClickSelector)); web2py.disableElement(form.find(web2py.formInputClickSelector));
web2py.hide_flash(); web2py.hide_flash();
web2py.ajax_page('post', url, form.serialize(), target, form); web2py.ajax_page('post', url, form.serialize(), target, form);
e.preventDefault(); e.preventDefault();
}); });
form.on('click', web2py.formInputClickSelector, function(e) { form.on('click', web2py.formInputClickSelector, function (e) {
e.preventDefault(); e.preventDefault();
var input_name = $(this).attr('name'); var input_name = $(this).attr('name');
if(input_name != undefined) { if (!web2py.isUndefined(input_name)) {
$('<input type="hidden" />').attr('name', input_name) $('<input type="hidden" />').attr('name', input_name)
.attr('value', $(this).val()).appendTo(form) .attr('value', $(this).val()).appendTo(form);
} }
form.trigger('submit'); form.trigger('submit');
}); });
}); });
}, },
ajax_page: function(method, action, data, target, element) { ajax_page: function (method, action, data, target, element) {
/* element is a new parameter, but should be put be put in front */ /* element is a new parameter, but should be put be put in front */
if(element == undefined) element = $(document); if (web2py.isUndefined(element)) element = $(document);
/* if target is not there, fill it with something that there isn't in the page*/ /* if target is not there, fill it with something that there isn't in the page*/
if(target == undefined || target == '') target = 'w2p_none'; if (web2py.isUndefined(target) || target === '') target = 'w2p_none';
if(web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */ if (web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */
$.ajax({ $.ajax({
'type': method, 'type': method,
'url': action, 'url': action,
'data': data, 'data': data,
'beforeSend': function(xhr, settings) { 'beforeSend': function (xhr, settings) {
xhr.setRequestHeader('web2py-component-location', document.location); xhr.setRequestHeader('web2py-component-location', document.location);
xhr.setRequestHeader('web2py-component-element', target); xhr.setRequestHeader('web2py-component-element', target);
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
}, },
'success': function(data, status, xhr) { 'success': function (data, status, xhr) {
/*bummer for form submissions....the element is not there after complete /*bummer for form submissions....the element is not there after complete
*because it gets replaced by the new response.... *because it gets replaced by the new response....
*/ */
web2py.fire(element, 'ajax:success', [data, status, xhr], target); web2py.fire(element, 'ajax:success', [data, status, xhr], target);
}, },
'error': function(xhr, status, error) { 'error': function (xhr, status, error) {
/*bummer for form submissions....in addition to the element being not there after /*bummer for form submissions....in addition to the element being not there after
*complete because it gets replaced by the new response, standard form *complete because it gets replaced by the new response, standard form
*handling just returns the same status code for good and bad *handling just returns the same status code for good and bad
@@ -317,7 +332,7 @@
*/ */
web2py.fire(element, 'ajax:error', [xhr, status, error], target); web2py.fire(element, 'ajax:error', [xhr, status, error], target);
}, },
'complete': function(xhr, status) { 'complete': function (xhr, status) {
web2py.fire(element, 'ajax:complete', [xhr, status], target); web2py.fire(element, 'ajax:complete', [xhr, status], target);
web2py.updatePage(xhr, target); /* Parse and load the html received */ web2py.updatePage(xhr, target); /* Parse and load the html received */
web2py.trap_form(action, target); web2py.trap_form(action, target);
@@ -327,33 +342,33 @@
}); });
} }
}, },
component: function(action, target, timeout, times, el) { component: function (action, target, timeout, times, el) {
/* element is a new parameter, but should be put in front */ /* element is a new parameter, but should be put in front */
$(function() { $(function () {
var jelement = $("#" + target); var jelement = $('#' + target);
var element = jelement.get(0); var element = jelement.get(0);
var statement = "jQuery('#" + target + "').get(0).reload();"; var statement = 'jQuery("#' + target + '").get(0).reload();';
element.reload = function() { element.reload = function () {
/* Continue if times is Infinity or /* Continue if times is Infinity or
* the times limit is not reached * the times limit is not reached
*/ */
if(element.reload_check()) { if (element.reload_check()) {
web2py.ajax_page('get', action, null, target, el); web2py.ajax_page('get', action, null, target, el);
} }
}; };
/* Method to check timing limit */ /* Method to check timing limit */
element.reload_check = function() { element.reload_check = function () {
if(jelement.hasClass('w2p_component_stop')) { if (jelement.hasClass('w2p_component_stop')) {
clearInterval(this.timing); clearInterval(this.timing);
return false; return false;
} }
if(this.reload_counter == Infinity) { if (this.reload_counter == Infinity) {
return true; return true;
} else { } else {
if(!isNaN(this.reload_counter)) { if (!isNaN(this.reload_counter)) {
this.reload_counter -= 1; this.reload_counter -= 1;
if(this.reload_counter < 0) { if (this.reload_counter < 0) {
if(!this.run_once) { if (!this.run_once) {
clearInterval(this.timing); clearInterval(this.timing);
return false; return false;
} }
@@ -364,10 +379,10 @@
} }
return false; return false;
}; };
if(!isNaN(timeout)) { if (!isNaN(timeout)) {
element.timeout = timeout; element.timeout = timeout;
element.reload_counter = times; element.reload_counter = times;
if(times > 1) { if (times > 1) {
/* Multiple or infinite reload /* Multiple or infinite reload
* Run first iteration * Run first iteration
*/ */
@@ -375,7 +390,7 @@
element.run_once = false; element.run_once = false;
element.timing = setInterval(statement, timeout); element.timing = setInterval(statement, timeout);
element.reload_counter -= 1; element.reload_counter -= 1;
} else if(times == 1) { } else if (times == 1) {
/* Run once with timeout */ /* Run once with timeout */
element.run_once = true; element.run_once = true;
element.setTimeout = setTimeout; element.setTimeout = setTimeout;
@@ -388,21 +403,21 @@
} }
}); });
}, },
updatePage: function(xhr, target) { updatePage: function (xhr, target) {
var t = $('#' + target); var t = $('#' + target);
var html = $.parseHTML(xhr.responseText, document, true); var html = $.parseHTML(xhr.responseText, document, true);
var title_elements = $(html).filter('title').add($(html).find('title')); var title_elements = $(html).filter('title').add($(html).find('title'));
var title = title_elements.last().text(); var title = title_elements.last().text();
if(title) { if (title) {
title_elements.remove(); /* Remove any title elements from the response */ title_elements.remove(); /* Remove any title elements from the response */
document.title = $.trim(title); /* Set the new document title */ document.title = $.trim(title); /* Set the new document title */
} }
var content = xhr.getResponseHeader('web2py-component-content'); var content = xhr.getResponseHeader('web2py-component-content');
if(content == 'prepend') t.prepend(xhr.responseText); if (content == 'prepend') t.prepend(xhr.responseText);
else if(content == 'append') t.append(xhr.responseText); else if (content == 'append') t.append(xhr.responseText);
else if(content != 'hide') t.html(html); else if (content != 'hide') t.html(html);
}, },
calc_entropy: function(mystring) { calc_entropy: function (mystring) {
/* calculate a simple entropy for a given string */ /* calculate a simple entropy for a given string */
var csets = new Array( var csets = new Array(
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
@@ -413,41 +428,41 @@
seen = {}, seen = {},
lastset = null, lastset = null,
mystringlist = mystring.split(''); mystringlist = mystring.split('');
for(var i = 0; i < mystringlist.length; i++) { /* classify this character */ for (var i = 0; i < mystringlist.length; i++) { /* classify this character */
var c = mystringlist[i], var c = mystringlist[i],
inset = 5; inset = 5;
for(var j = 0; j < csets.length; j++) for (var j = 0; j < csets.length; j++)
if(csets[j].indexOf(c) != -1) { if (csets[j].indexOf(c) != -1) {
inset = j; inset = j;
break; break;
} }
/*calculate effect of character on alphabet size */ /*calculate effect of character on alphabet size */
if(!(inset in seen)) { if (!(inset in seen)) {
seen[inset] = 1; seen[inset] = 1;
score += csets[inset].length; score += csets[inset].length;
} else if(!(c in other)) { } else if (!(c in other)) {
score += 1; score += 1;
other[c] = 1; other[c] = 1;
} }
if(inset != lastset) { if (inset != lastset) {
score += 1; score += 1;
lastset = inset; lastset = inset;
} }
} }
var entropy = mystring.length * Math.log(score) / 0.6931471805599453; var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
return Math.round(entropy * 100) / 100 return Math.round(entropy * 100) / 100;
}, },
validate_entropy: function(myfield, req_entropy) { validate_entropy: function (myfield, req_entropy) {
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy'); if (!web2py.isUndefined(myfield.data('w2p_entropy'))) req_entropy = myfield.data('w2p_entropy');
var validator = function() { var validator = function () {
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy; var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
var r = 0, var r = 0,
g = 0, g = 0,
b = 0, b = 0,
rs = function(x) { rs = function (x) {
return Math.round(x * 15).toString(16) return Math.round(x * 15).toString(16);
}; };
if(v <= 0.5) { if (v <= 0.5) {
r = 1.0; r = 1.0;
g = 2.0 * v; g = 2.0 * v;
} else { } else {
@@ -456,17 +471,18 @@
} }
var color = '#' + rs(r) + rs(g) + rs(b); var color = '#' + rs(r) + rs(g) + rs(b);
myfield.css('background-color', color); myfield.css('background-color', color);
entropy_callback = myfield.data('entropy_callback'); var entropy_callback = myfield.data('entropy_callback');
if(entropy_callback) entropy_callback(v); if (entropy_callback) entropy_callback(v);
} };
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check'); if (!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator)
.addClass('entropy_check');
}, },
web2py_websocket: function(url, onmessage, onopen, onclose) { web2py_websocket: function (url, onmessage, onopen, onclose) {
if("WebSocket" in window) { if ('WebSocket' in window) {
var ws = new WebSocket(url); var ws = new WebSocket(url);
ws.onopen = onopen ? onopen : (function() {}); ws.onopen = onopen ? onopen : (function () {});
ws.onmessage = onmessage; ws.onmessage = onmessage;
ws.onclose = onclose ? onclose : (function() {}); ws.onclose = onclose ? onclose : (function () {});
return true; /* supported */ return true; /* supported */
} else return false; /* not supported */ } else return false; /* not supported */
}, },
@@ -478,7 +494,7 @@
/* Form input elements re-enabled after form submission */ /* Form input elements re-enabled after form submission */
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled', enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
/* Triggers an event on an element and returns false if the event result is false */ /* Triggers an event on an element and returns false if the event result is false */
fire: function(obj, type, data, target) { fire: function (obj, type, data, target) {
var event = $.Event(type, { var event = $.Event(type, {
'containerTarget': $('#' + target)[0] 'containerTarget': $('#' + target)[0]
}); });
@@ -486,45 +502,50 @@
return event.result !== false; return event.result !== false;
}, },
/* Helper function, needed to provide consistent behavior in IE */ /* Helper function, needed to provide consistent behavior in IE */
stopEverything: function(e) { stopEverything: function (e) {
$(e.target).trigger('w2p:everythingStopped'); $(e.target).trigger('w2p:everythingStopped');
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}, },
confirm: function(message) { confirm: function (message) {
return confirm(message); return confirm(message);
}, },
/* replace element's html with the 'data-disable-with' after storing original html /* replace element's html with the 'data-disable-with' after storing original html
* and prevent clicking on it */ * and prevent clicking on it */
disableElement: function(el) { disableElement: function (el) {
if (!web2py.isUndefined(el.data('w2p_disable'))) {
return false;
}
el.addClass('disabled'); el.addClass('disabled');
var method = el.is('input') ? 'val' : 'html'; var method = el.is('input') ? 'val' : 'html';
//method = el.attr('name') ? 'html' : 'val'; //method = el.attr('name') ? 'html' : 'val';
var disable_with_message = (typeof w2p_ajax_disable_with_message != 'undefined') ? w2p_ajax_disable_with_message : "Working..."; var disable_with_message = (!web2py.isUndefined(w2p_ajax_disable_with_message)) ?
w2p_ajax_disable_with_message : 'Working...';
/*store enabled state if not already disabled */ /*store enabled state if not already disabled */
if(el.data('w2p_enable_with') === undefined) { if (web2py.isUndefined(el.data('w2p_enable_with'))) {
el.data('w2p_enable_with', el[method]()); el.data('w2p_enable_with', el[method]());
} }
/*if you don't want to see "working..." on buttons, replace the following /*if you don't want to see "working..." on buttons, replace the following
* two lines with this one * two lines with this one
* el.data('w2p_disable_with', el[method]()); * el.data('w2p_disable_with', el[method]());
*/ */
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) { if ((el.data('w2p_disable_with') == 'default') || (web2py.isUndefined(el.data(
'w2p_disable_with')))) {
el.data('w2p_disable_with', disable_with_message); el.data('w2p_disable_with', disable_with_message);
} }
/* set to disabled state*/ /* set to disabled state*/
el[method](el.data('w2p_disable_with')); el[method](el.data('w2p_disable_with'));
el.bind('click.w2pDisable', function(e) { /* prevent further clicking*/ el.bind('click.w2pDisable', function (e) { /* prevent further clicking*/
return web2py.stopEverything(e); return web2py.stopEverything(e);
}); });
}, },
/* restore element to its original state which was disabled by 'disableElement' above*/ /* restore element to its original state which was disabled by 'disableElement' above*/
enableElement: function(el) { enableElement: function (el) {
var method = el.is('input') ? 'val' : 'html'; var method = el.is('input') ? 'val' : 'html';
if(el.data('w2p_enable_with') !== undefined) { if (!web2py.isUndefined(el.data('w2p_enable_with'))) {
/* set to old enabled state */ /* set to old enabled state */
el[method](el.data('w2p_enable_with')); el[method](el.data('w2p_enable_with'));
el.removeData('w2p_enable_with'); el.removeData('w2p_enable_with');
@@ -533,47 +554,47 @@
el.unbind('click.w2pDisable'); el.unbind('click.w2pDisable');
}, },
/*convenience wrapper, internal use only */ /*convenience wrapper, internal use only */
simple_component: function(action, target, element) { simple_component: function (action, target, element) {
web2py.component(action, target, 0, 1, element); web2py.component(action, target, 0, 1, element);
}, },
/*helper for flash messages*/ /*helper for flash messages*/
flash: function(message, status) { flash: function (message, status) {
var flash = $('.w2p_flash'); var flash = $('.w2p_flash');
web2py.hide_flash(); web2py.hide_flash();
flash.html(message).addClass(status); flash.html(message).addClass(status);
if(flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown(); if (flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown();
}, },
hide_flash: function() { hide_flash: function () {
$('.w2p_flash').fadeOut(0).html(''); $('.w2p_flash').fadeOut(0).html('');
}, },
show_if_handler: function(target) { show_if_handler: function (target) {
var triggers = {}; var triggers = {};
var show_if = function() { var show_if = function () {
var t = $(this); var t = $(this);
var id = t.attr('id'); var id = t.attr('id');
t.attr('value', t.val()); t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) { for (var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target); var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target); var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown(); if (t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide(); else tr.hide();
} }
}; };
$('[data-show-trigger]', target).each(function() { $('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger'); var name = $(this).attr('data-show-trigger');
// The field exists only when creating/editing a row // The field exists only when creating/editing a row
if($('#' + name).length) { if ($('#' + name).length) {
if(!triggers[name]) triggers[name] = []; if (!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id')); triggers[name].push($(this).attr('id'));
} }
}); });
for(var name in triggers) { for (var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if); $('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target)); show_if.call($('#' + name, target));
}; }
}, },
component_handler: function(target) { component_handler: function (target) {
$('div[data-w2p_remote]', target).each(function() { $('div[data-w2p_remote]', target).each(function () {
var remote, times, timeout, target; var remote, times, timeout, target;
var el = $(this); var el = $(this);
remote = el.data('w2p_remote'); remote = el.data('w2p_remote');
@@ -581,9 +602,9 @@
timeout = el.data('w2p_timeout'); timeout = el.data('w2p_timeout');
target = el.attr('id'); target = el.attr('id');
web2py.component(remote, target, timeout, times, $(this)); web2py.component(remote, target, timeout, times, $(this));
}) });
}, },
a_handler: function(el, e) { a_handler: function (el, e) {
e.preventDefault(); e.preventDefault();
var method = el.data('w2p_method'); var method = el.data('w2p_method');
var action = el.attr('href'); var action = el.attr('href');
@@ -591,55 +612,56 @@
var confirm_message = el.data('w2p_confirm'); var confirm_message = el.data('w2p_confirm');
var pre_call = el.data('w2p_pre_call'); var pre_call = el.data('w2p_pre_call');
if(pre_call != undefined) { if (!web2py.isUndefined(pre_call)) {
eval(pre_call); eval(pre_call);
} }
if(confirm_message) { if (confirm_message) {
if(confirm_message == 'default') if (confirm_message == 'default') {
confirm_message = w2p_ajax_confirm_message || confirm_message = w2p_ajax_confirm_message ||
'Are you sure you want to delete this object?'; 'Are you sure you want to delete this object?';
if(!web2py.confirm(confirm_message)) { }
if (!web2py.confirm(confirm_message)) {
web2py.stopEverything(e); web2py.stopEverything(e);
return; return;
} }
} }
if(target == undefined) { if (web2py.isUndefined(target)) {
if(method == 'GET') { if (method == 'GET') {
web2py.ajax_page('get', action, [], '', el); web2py.ajax_page('get', action, [], '', el);
} else if(method == 'POST') { } else if (method == 'POST') {
web2py.ajax_page('post', action, [], '', el); web2py.ajax_page('post', action, [], '', el);
} }
} else { } else {
if(method == 'GET') { if (method == 'GET') {
web2py.ajax_page('get', action, [], target, el); web2py.ajax_page('get', action, [], target, el);
} else if(method == 'POST') { } else if (method == 'POST') {
web2py.ajax_page('post', action, [], target, el); web2py.ajax_page('post', action, [], target, el);
} }
} }
}, },
a_handlers: function() { a_handlers: function () {
var el = $(document); var el = $(document);
el.on('click', 'a[data-w2p_method]', function(e) { el.on('click', 'a[data-w2p_method]', function (e) {
web2py.a_handler($(this), e); web2py.a_handler($(this), e);
}); });
/* removal of element should happen only on success */ /* removal of element should happen only on success */
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function(e) { el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function () {
var el = $(this); var el = $(this);
var toremove = el.data('w2p_remove'); var toremove = el.data('w2p_remove');
if(toremove != undefined) { if (!web2py.isUndefined(toremove)) {
toremove = el.closest(toremove); toremove = el.closest(toremove);
if(!toremove.length) { if (!toremove.length) {
/*this enables removal of whatever selector if a closest is not found */ /*this enables removal of whatever selector if a closest is not found */
toremove = $(toremove); toremove = $(toremove);
} }
toremove.remove(); toremove.remove();
} }
}); });
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function(e) { el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function () {
web2py.disableElement($(this)); web2py.disableElement($(this));
}); });
/*re-enable click on completion*/ /*re-enable click on completion*/
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function(e) { el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function () {
web2py.enableElement($(this)); web2py.enableElement($(this));
}); });
}, },
@@ -648,15 +670,19 @@
- Replaces element text with value of 'data-disable-with' attribute - Replaces element text with value of 'data-disable-with' attribute
- Sets disabled property to true - Sets disabled property to true
*/ */
disableFormElements: function(form) { disableFormElements: function (form) {
form.find(web2py.disableSelector).each(function() { form.find(web2py.disableSelector).each(function () {
var element = $(this), var element = $(this),
method = element.is('button') ? 'html' : 'val'; method = element.is('button') ? 'html' : 'val';
var disable_with = element.data('w2p_disable_with'); var disable_with = element.data('w2p_disable_with');
if(disable_with == undefined) { var disable = element.data('w2p_disable');
element.data('w2p_disable_with', element[method]()) if (!web2py.isUndefined(disable)) {
return false;
} }
if(element.data('w2p_enable_with') === undefined) { if (web2py.isUndefined(disable_with)) {
element.data('w2p_disable_with', element[method]());
}
if (web2py.isUndefined(element.data('w2p_enable_with'))) {
element.data('w2p_enable_with', element[method]()); element.data('w2p_enable_with', element[method]());
} }
element[method](element.data('w2p_disable_with')); element[method](element.data('w2p_disable_with'));
@@ -668,50 +694,50 @@
- Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`) - Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`)
- Sets disabled property to false - Sets disabled property to false
*/ */
enableFormElements: function(form) { enableFormElements: function (form) {
form.find(web2py.enableSelector).each(function() { form.find(web2py.enableSelector).each(function () {
var element = $(this), var element = $(this),
method = element.is('button') ? 'html' : 'val'; method = element.is('button') ? 'html' : 'val';
if(element.data('w2p_enable_with')) { if (element.data('w2p_enable_with')) {
element[method](element.data('w2p_enable_with')); element[method](element.data('w2p_enable_with'));
element.removeData('w2p_enable_with'); element.removeData('w2p_enable_with');
} }
element.prop('disabled', false); element.prop('disabled', false);
}); });
}, },
form_handlers: function() { form_handlers: function () {
var el = $(document); var el = $(document);
el.on('ajax:beforeSend', 'form[data-w2p_target]', function(e) { el.on('ajax:beforeSend', 'form[data-w2p_target]', function () {
web2py.disableFormElements($(this)); web2py.disableFormElements($(this));
}); });
el.on('ajax:complete', 'form[data-w2p_target]', function(e) { el.on('ajax:complete', 'form[data-w2p_target]', function () {
web2py.enableFormElements($(this)); web2py.enableFormElements($(this));
}); });
}, },
/* Invalidate and force reload of a web2py component /* Invalidate and force reload of a web2py component
*/ */
invalidate: function(target) { invalidate: function (target) {
$('div[data-w2p_remote]', target).each(function() { $('div[data-w2p_remote]', target).each(function () {
var el = $('#' + $(this).attr('id')).get(0); var el = $('#' + $(this).attr('id')).get(0);
if(el.timing !== undefined) { // Block triggering regular routines if (!web2py.isUndefined(el.timing)) { // Block triggering regular routines
clearInterval(el.timing); clearInterval(el.timing);
} }
}); });
$.web2py.component_handler(target); $.web2py.component_handler(target);
}, },
main_hook: function() { main_hook: function () {
var flash = $('.w2p_flash'); var flash = $('.w2p_flash');
flash.hide(); flash.hide();
if(flash.html()) web2py.flash(flash.html()); if (flash.html()) web2py.flash(flash.html());
web2py.ajax_init(document); web2py.ajax_init(document);
web2py.event_handlers(); web2py.event_handlers();
web2py.a_handlers(); web2py.a_handlers();
web2py.form_handlers(); web2py.form_handlers();
} }
} };
/*end of functions */ /*end of functions */
/*main hook*/ /*main hook*/
$(function() { $(function () {
web2py.main_hook(); web2py.main_hook();
}); });
+224 -198
View File
@@ -1,4 +1,4 @@
(function($, undefined) { (function ($, undefined) {
/* /*
* Unobtrusive scripting adapter for jQuery, largely taken from * Unobtrusive scripting adapter for jQuery, largely taken from
* the wonderful https://github.com/rails/jquery-ujs * the wonderful https://github.com/rails/jquery-ujs
@@ -7,68 +7,72 @@
* Released under the MIT license * Released under the MIT license
* *
*/ */
if($.web2py !== undefined) { 'use strict';
if ($.web2py !== undefined) {
$.error('web2py.js has already been loaded!'); $.error('web2py.js has already been loaded!');
} }
String.prototype.reverse = function () {
String.prototype.reverse = function() {
return this.split('').reverse().join(''); return this.split('').reverse().join('');
}; };
var web2py; var web2py;
$.web2py = web2py = { $.web2py = web2py = {
popup: function(url) { isUndefined: function (obj) {
/* grabbed from underscore.js */
return obj === void 0;
},
popup: function (url) {
/* popup a window */ /* popup a window */
newwindow = window.open(url, 'name', 'height=400,width=600'); var newwindow = window.open(url, 'name', 'height=400,width=600');
if(window.focus) newwindow.focus(); if (window.focus) newwindow.focus();
return false; return false;
}, },
collapse: function(id) { collapse: function (id) {
/* toggle an element */ /* toggle an element */
$('#' + id).slideToggle(); $('#' + id).slideToggle();
}, },
fade: function(id, value) { fade: function (id, value) {
/*fade something*/ /*fade something*/
if(value > 0) $('#' + id).hide().fadeIn('slow'); if (value > 0) $('#' + id).hide().fadeIn('slow');
else $('#' + id).show().fadeOut('slow'); else $('#' + id).show().fadeOut('slow');
}, },
ajax: function(u, s, t) { ajax: function (u, s, t) {
/*simple ajax function*/ /*simple ajax function*/
query = ''; var query = '';
if(typeof s == "string") { if (typeof s == 'string') {
d = $(s).serialize(); var d = $(s).serialize();
if(d) { if (d) {
query = d; query = d;
} }
} else { } else {
pcs = []; var pcs = [];
if(s != null && s != undefined) if (s !== null && !web2py.isUndefined(s))
for(i = 0; i < s.length; i++) { for (var i = 0; i < s.length; i++) {
q = $("[name=" + s[i] + "]").serialize(); var q = $('[name=' + s[i] + ']').serialize();
if(q) { if (q) {
pcs.push(q); pcs.push(q);
} }
} }
if(pcs.length > 0) { if (pcs.length > 0) {
query = pcs.join("&"); query = pcs.join('&');
} }
} }
$.ajax({ $.ajax({
type: "POST", type: 'POST',
url: u, url: u,
data: query, data: query,
success: function(msg) { success: function (msg) {
if(t) { if (t) {
if(t == ':eval') eval(msg); if (t == ':eval') eval(msg);
else if(typeof t == 'string') $("#" + t).html(msg); else if (typeof t == 'string') $('#' + t).html(msg);
else t(msg); else t(msg);
} }
} }
}); });
}, },
ajax_fields: function(target) { ajax_fields: function (target) {
/* /*
*this attaches something to a newly loaded fragment/page *this attaches something to a newly loaded fragment/page
* Ideally all events should be bound to the document, so we can avoid calling * Ideally all events should be bound to the document, so we can avoid calling
@@ -76,29 +80,31 @@
*/ */
/*adds btn class to buttons*/ /*adds btn class to buttons*/
$('button:not([class^="btn"])', target).addClass('btn'); $('button:not([class^="btn"])', target).addClass('btn');
$('form input[type="submit"]:not([class^="btn"]), form input[type="button"]:not([class^="btn"])', target).addClass('btn'); $(
'form input[type="submit"]:not([class^="btn"]), form input[type="button"]:not([class^="btn"])',
target).addClass('btn');
/* javascript for PasswordWidget*/ /* javascript for PasswordWidget*/
$('input[type=password][data-w2p_entropy]', target).each(function() { $('input[type=password][data-w2p_entropy]', target).each(function () {
web2py.validate_entropy($(this)); web2py.validate_entropy($(this));
}); });
/* javascript for ListWidget*/ /* javascript for ListWidget*/
$('ul.w2p_list', target).each(function() { $('ul.w2p_list', target).each(function () {
function pe(ul, e) { function pe(ul, e) {
var new_line = ml(ul); var new_line = ml(ul);
rel(ul); rel(ul);
if($(e.target).parent().is(':visible')) { if ($(e.target).parent().is(':visible')) {
/* make sure we didn't delete the element before we insert after */ /* make sure we didn't delete the element before we insert after */
new_line.insertAfter($(e.target).parent()); new_line.insertAfter($(e.target).parent());
} else { } else {
/* the line we clicked on was deleted, just add to end of list */ /* the line we clicked on was deleted, just add to end of list */
new_line.appendTo(ul); new_line.appendTo(ul);
} }
new_line.find(":text").focus(); new_line.find(':text').focus();
return false; return false;
} }
function rl(ul, e) { function rl(ul, e) {
if($(ul).children().length > 1) { if ($(ul).children().length > 1) {
/* only remove if we have more than 1 item so the list is never empty */ /* only remove if we have more than 1 item so the list is never empty */
$(e.target).parent().remove(); $(e.target).parent().remove();
} }
@@ -106,32 +112,33 @@
function ml(ul) { function ml(ul) {
/* clone the first field */ /* clone the first field */
var line = $(ul).find("li:first").clone(true); var line = $(ul).find('li:first').clone(true);
line.find(':text').val(''); line.find(':text').val('');
return line; return line;
} }
function rel(ul) { function rel(ul) {
/* keep only as many as needed*/ /* keep only as many as needed*/
$(ul).find("li").each(function() { $(ul).find('li').each(function () {
var trimmed = $.trim($(this.firstChild).val()); var trimmed = $.trim($(this.firstChild).val());
if(trimmed == '') $(this).remove(); if (trimmed === '') $(this).remove();
else $(this.firstChild).val(trimmed); else $(this.firstChild).val(trimmed);
}); });
} }
var ul = this; var ul = this;
$(ul).find(":text").after('<a href="#">+</a>&nbsp;<a href="#">-</a>').keypress(function(e) { $(ul).find(':text').after('<a href="#">+</a>&nbsp;<a href="#">-</a>').keypress(
return(e.which == 13) ? pe(ul, e) : true; function (e) {
}).next().click(function(e) { return (e.which == 13) ? pe(ul, e) : true;
}).next().click(function (e) {
pe(ul, e); pe(ul, e);
e.preventDefault(); e.preventDefault();
}).next().click(function(e) { }).next().click(function (e) {
rl(ul, e); rl(ul, e);
e.preventDefault(); e.preventDefault();
}); });
}); });
}, },
ajax_init: function(target) { ajax_init: function (target) {
/*called whenever a fragment gets loaded */ /*called whenever a fragment gets loaded */
$('.w2p_hidden', target).hide(); $('.w2p_hidden', target).hide();
web2py.manage_errors(target); web2py.manage_errors(target);
@@ -140,68 +147,71 @@
web2py.component_handler(target); web2py.component_handler(target);
}, },
/* manage errors in forms */ /* manage errors in forms */
manage_errors: function(target) { manage_errors: function (target) {
$('div.error', target).hide().slideDown('slow'); $('div.error', target).hide().slideDown('slow');
}, },
after_ajax: function(xhr) { after_ajax: function (xhr) {
/* called whenever an ajax request completes */ /* called whenever an ajax request completes */
var command = xhr.getResponseHeader('web2py-component-command'); var command = xhr.getResponseHeader('web2py-component-command');
var flash = xhr.getResponseHeader('web2py-component-flash'); var flash = xhr.getResponseHeader('web2py-component-flash');
if(command !== null) { if (command !== null) {
eval(decodeURIComponent(command)); eval(decodeURIComponent(command));
} }
if(flash) { if (flash) {
web2py.flash(decodeURIComponent(flash)) web2py.flash(decodeURIComponent(flash));
} }
}, },
event_handlers: function() { event_handlers: function () {
/* /*
* This is called once for page * This is called once for page
* Ideally it should bound all the things that are needed * Ideally it should bound all the things that are needed
* and require no dom manipulations * and require no dom manipulations
*/ */
var doc = $(document); var doc = $(document);
doc.on('click', '.w2p_flash', function(e) { doc.on('click', '.w2p_flash', function () {
var t = $(this); var t = $(this);
if(t.css('top') == '0px') t.slideUp('slow'); if (t.css('top') == '0px') t.slideUp('slow');
else t.fadeOut(); else t.fadeOut();
}); });
doc.on('keyup', 'input.integer', function() { doc.on('keyup', 'input.integer', function () {
var nvalue = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse(); var nvalue = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
if(this.value != nvalue) this.value = nvalue; if (this.value != nvalue) this.value = nvalue;
}); });
doc.on('keyup', 'input.double, input.decimal', function() { doc.on('keyup', 'input.double, input.decimal', function () {
var nvalue = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse(); var nvalue = this.value.reverse().replace(
if(this.value != nvalue) this.value = nvalue; /[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
if (this.value != nvalue) this.value = nvalue;
}); });
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?"; var confirm_message = !web2py.isUndefined(w2p_ajax_confirm_message) ? w2p_ajax_confirm_message :
doc.on('click', "input[type='checkbox'].delete", function() { 'Are you sure you want to delete this object?';
if(this.checked) doc.on('click', 'input[type="checkbox"].delete', function () {
if(!web2py.confirm(confirm_message)) this.checked = false; if (this.checked)
if (!web2py.confirm(confirm_message)) this.checked = false;
}); });
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S"; var datetime_format = !web2py.isUndefined(w2p_ajax_datetime_format) ? w2p_ajax_datetime_format :
doc.on('click', "input.datetime", function() { '%Y-%m-%d %H:%M:%S';
doc.on('click', 'input.datetime', function () {
var tformat = $(this).data('w2p_datetime_format'); var tformat = $(this).data('w2p_datetime_format');
var active = $(this).data('w2p_datetime'); var active = $(this).data('w2p_datetime');
var format = (typeof tformat != 'undefined') ? tformat : datetime_format; var format = !web2py.isUndefined(tformat) ? tformat : datetime_format;
if(active === undefined) { if (active === undefined) {
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: format, ifFormat: format,
showsTime: true, showsTime: true,
timeFormat: "24" timeFormat: '24'
}); });
$(this).attr('autocomplete', 'off'); $(this).attr('autocomplete', 'off');
$(this).data('w2p_datetime', 1); $(this).data('w2p_datetime', 1);
$(this).trigger('click'); $(this).trigger('click');
} }
}); });
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d"; var date_format = !web2py.isUndefined(w2p_ajax_date_format) ? w2p_ajax_date_format : '%Y-%m-%d';
doc.on('click', "input.date", function() { doc.on('click', 'input.date', function () {
var tformat = $(this).data('w2p_date_format'); var tformat = $(this).data('w2p_date_format');
var active = $(this).data('w2p_date'); var active = $(this).data('w2p_date');
var format = (typeof tformat != 'undefined') ? tformat : date_format; var format = !web2py.isUndefined(tformat) ? tformat : date_format;
if(active === undefined) { if (active === undefined) {
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: format, ifFormat: format,
@@ -212,9 +222,9 @@
$(this).trigger('click'); $(this).trigger('click');
} }
}); });
doc.on('focus', "input.time", function() { doc.on('focus', 'input.time', function () {
var active = $(this).data('w2p_time'); var active = $(this).data('w2p_time');
if(active === undefined) { if (web2py.isUndefined(active)) {
$(this).timeEntry({ $(this).timeEntry({
spinnerImage: '' spinnerImage: ''
}).attr('autocomplete', 'off'); }).attr('autocomplete', 'off');
@@ -222,94 +232,99 @@
} }
}); });
/* help preventing double form submission for normal form (not LOADed) */ /* help preventing double form submission for normal form (not LOADed) */
$(doc).on('submit', 'form', function() { $(doc).on('submit', 'form', function () {
var submit_button = $(this).find(web2py.formInputClickSelector); var submit_button = $(this).find(web2py.formInputClickSelector);
web2py.disableElement(submit_button); web2py.disableElement(submit_button);
/* safeguard in case the form doesn't trigger a refresh,
see https://github.com/web2py/web2py/issues/1100 */
setTimeout(function () {
web2py.enableElement(submit_button);
}, 5000);
}); });
doc.ajaxSuccess(function(e, xhr) { doc.ajaxSuccess(function (e, xhr) {
var redirect = xhr.getResponseHeader('web2py-redirect-location'); var redirect = xhr.getResponseHeader('web2py-redirect-location');
if(redirect !== null) { if (redirect !== null) {
window.location = redirect; window.location = redirect;
}; }
/* run this here only if this Ajax request is NOT for a web2py component. */ /* run this here only if this Ajax request is NOT for a web2py component. */
if(xhr.getResponseHeader('web2py-component-content') == null) { if (xhr.getResponseHeader('web2py-component-content') === null) {
web2py.after_ajax(xhr); web2py.after_ajax(xhr);
}; }
}); });
doc.ajaxError(function(e, xhr, settings, exception) { doc.ajaxError(function (e, xhr, settings, exception) {
/*personally I don't like it. /*personally I don't like it.
*if there's an error it it flashed and can be removed *if there's an error it it flashed and can be removed
*as any other message *as any other message
*doc.off('click', '.w2p_flash') *doc.off('click', '.w2p_flash')
*/ */
switch(xhr.status) { switch (xhr.status) {
case 500: case 500:
web2py.flash(ajax_error_500); web2py.flash(ajax_error_500);
} }
}); });
}, },
trap_form: function(action, target) { trap_form: function (action, target) {
/* traps any LOADed form */ /* traps any LOADed form */
$('#' + target + ' form').each(function(i) { $('#' + target + ' form').each(function () {
var form = $(this); var form = $(this);
if(form.hasClass('no_trap')) { if (form.hasClass('no_trap')) {
return; return;
} }
var w2p_target = $(this).attr('data-w2p_target'); var w2p_target = $(this).attr('data-w2p_target');
if (typeof w2p_target === typeof undefined || w2p_target === false) { if (web2py.isUndefined(w2p_target) || w2p_target === false) {
form.attr('data-w2p_target', target); form.attr('data-w2p_target', target);
} else { } else {
target = w2p_target; target = w2p_target;
} }
var url = form.attr('action'); var url = form.attr('action');
if((url === "") || (url === "#") || (typeof url === 'undefined')) { if ((url === '') || (url === '#') || web2py.isUndefined(url)) {
/* form has no action. Use component url. */ /* form has no action. Use component url. */
url = action; url = action;
} }
form.submit(function(e) { form.submit(function (e) {
web2py.disableElement(form.find(web2py.formInputClickSelector)); web2py.disableElement(form.find(web2py.formInputClickSelector));
web2py.hide_flash(); web2py.hide_flash();
web2py.ajax_page('post', url, form.serialize(), target, form); web2py.ajax_page('post', url, form.serialize(), target, form);
e.preventDefault(); e.preventDefault();
}); });
form.on('click', web2py.formInputClickSelector, function(e) { form.on('click', web2py.formInputClickSelector, function (e) {
e.preventDefault(); e.preventDefault();
var input_name = $(this).attr('name'); var input_name = $(this).attr('name');
if(input_name != undefined) { if (!web2py.isUndefined(input_name)) {
$('<input type="hidden" />').attr('name', input_name) $('<input type="hidden" />').attr('name', input_name)
.attr('value', $(this).val()).appendTo(form) .attr('value', $(this).val()).appendTo(form);
} }
form.trigger('submit'); form.trigger('submit');
}); });
}); });
}, },
ajax_page: function(method, action, data, target, element) { ajax_page: function (method, action, data, target, element) {
/* element is a new parameter, but should be put be put in front */ /* element is a new parameter, but should be put be put in front */
if(element == undefined) element = $(document); if (web2py.isUndefined(element)) element = $(document);
/* if target is not there, fill it with something that there isn't in the page*/ /* if target is not there, fill it with something that there isn't in the page*/
if(target == undefined || target == '') target = 'w2p_none'; if (web2py.isUndefined(target) || target === '') target = 'w2p_none';
if(web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */ if (web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */
$.ajax({ $.ajax({
'type': method, 'type': method,
'url': action, 'url': action,
'data': data, 'data': data,
'beforeSend': function(xhr, settings) { 'beforeSend': function (xhr, settings) {
xhr.setRequestHeader('web2py-component-location', document.location); xhr.setRequestHeader('web2py-component-location', document.location);
xhr.setRequestHeader('web2py-component-element', target); xhr.setRequestHeader('web2py-component-element', target);
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
}, },
'success': function(data, status, xhr) { 'success': function (data, status, xhr) {
/*bummer for form submissions....the element is not there after complete /*bummer for form submissions....the element is not there after complete
*because it gets replaced by the new response.... *because it gets replaced by the new response....
*/ */
web2py.fire(element, 'ajax:success', [data, status, xhr], target); web2py.fire(element, 'ajax:success', [data, status, xhr], target);
}, },
'error': function(xhr, status, error) { 'error': function (xhr, status, error) {
/*bummer for form submissions....in addition to the element being not there after /*bummer for form submissions....in addition to the element being not there after
*complete because it gets replaced by the new response, standard form *complete because it gets replaced by the new response, standard form
*handling just returns the same status code for good and bad *handling just returns the same status code for good and bad
@@ -317,7 +332,7 @@
*/ */
web2py.fire(element, 'ajax:error', [xhr, status, error], target); web2py.fire(element, 'ajax:error', [xhr, status, error], target);
}, },
'complete': function(xhr, status) { 'complete': function (xhr, status) {
web2py.fire(element, 'ajax:complete', [xhr, status], target); web2py.fire(element, 'ajax:complete', [xhr, status], target);
web2py.updatePage(xhr, target); /* Parse and load the html received */ web2py.updatePage(xhr, target); /* Parse and load the html received */
web2py.trap_form(action, target); web2py.trap_form(action, target);
@@ -327,33 +342,33 @@
}); });
} }
}, },
component: function(action, target, timeout, times, el) { component: function (action, target, timeout, times, el) {
/* element is a new parameter, but should be put in front */ /* element is a new parameter, but should be put in front */
$(function() { $(function () {
var jelement = $("#" + target); var jelement = $('#' + target);
var element = jelement.get(0); var element = jelement.get(0);
var statement = "jQuery('#" + target + "').get(0).reload();"; var statement = 'jQuery("#' + target + '").get(0).reload();';
element.reload = function() { element.reload = function () {
/* Continue if times is Infinity or /* Continue if times is Infinity or
* the times limit is not reached * the times limit is not reached
*/ */
if(element.reload_check()) { if (element.reload_check()) {
web2py.ajax_page('get', action, null, target, el); web2py.ajax_page('get', action, null, target, el);
} }
}; };
/* Method to check timing limit */ /* Method to check timing limit */
element.reload_check = function() { element.reload_check = function () {
if(jelement.hasClass('w2p_component_stop')) { if (jelement.hasClass('w2p_component_stop')) {
clearInterval(this.timing); clearInterval(this.timing);
return false; return false;
} }
if(this.reload_counter == Infinity) { if (this.reload_counter == Infinity) {
return true; return true;
} else { } else {
if(!isNaN(this.reload_counter)) { if (!isNaN(this.reload_counter)) {
this.reload_counter -= 1; this.reload_counter -= 1;
if(this.reload_counter < 0) { if (this.reload_counter < 0) {
if(!this.run_once) { if (!this.run_once) {
clearInterval(this.timing); clearInterval(this.timing);
return false; return false;
} }
@@ -364,10 +379,10 @@
} }
return false; return false;
}; };
if(!isNaN(timeout)) { if (!isNaN(timeout)) {
element.timeout = timeout; element.timeout = timeout;
element.reload_counter = times; element.reload_counter = times;
if(times > 1) { if (times > 1) {
/* Multiple or infinite reload /* Multiple or infinite reload
* Run first iteration * Run first iteration
*/ */
@@ -375,7 +390,7 @@
element.run_once = false; element.run_once = false;
element.timing = setInterval(statement, timeout); element.timing = setInterval(statement, timeout);
element.reload_counter -= 1; element.reload_counter -= 1;
} else if(times == 1) { } else if (times == 1) {
/* Run once with timeout */ /* Run once with timeout */
element.run_once = true; element.run_once = true;
element.setTimeout = setTimeout; element.setTimeout = setTimeout;
@@ -388,21 +403,21 @@
} }
}); });
}, },
updatePage: function(xhr, target) { updatePage: function (xhr, target) {
var t = $('#' + target); var t = $('#' + target);
var html = $.parseHTML(xhr.responseText, document, true); var html = $.parseHTML(xhr.responseText, document, true);
var title_elements = $(html).filter('title').add($(html).find('title')); var title_elements = $(html).filter('title').add($(html).find('title'));
var title = title_elements.last().text(); var title = title_elements.last().text();
if(title) { if (title) {
title_elements.remove(); /* Remove any title elements from the response */ title_elements.remove(); /* Remove any title elements from the response */
document.title = $.trim(title); /* Set the new document title */ document.title = $.trim(title); /* Set the new document title */
} }
var content = xhr.getResponseHeader('web2py-component-content'); var content = xhr.getResponseHeader('web2py-component-content');
if(content == 'prepend') t.prepend(xhr.responseText); if (content == 'prepend') t.prepend(xhr.responseText);
else if(content == 'append') t.append(xhr.responseText); else if (content == 'append') t.append(xhr.responseText);
else if(content != 'hide') t.html(html); else if (content != 'hide') t.html(html);
}, },
calc_entropy: function(mystring) { calc_entropy: function (mystring) {
/* calculate a simple entropy for a given string */ /* calculate a simple entropy for a given string */
var csets = new Array( var csets = new Array(
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
@@ -413,41 +428,41 @@
seen = {}, seen = {},
lastset = null, lastset = null,
mystringlist = mystring.split(''); mystringlist = mystring.split('');
for(var i = 0; i < mystringlist.length; i++) { /* classify this character */ for (var i = 0; i < mystringlist.length; i++) { /* classify this character */
var c = mystringlist[i], var c = mystringlist[i],
inset = 5; inset = 5;
for(var j = 0; j < csets.length; j++) for (var j = 0; j < csets.length; j++)
if(csets[j].indexOf(c) != -1) { if (csets[j].indexOf(c) != -1) {
inset = j; inset = j;
break; break;
} }
/*calculate effect of character on alphabet size */ /*calculate effect of character on alphabet size */
if(!(inset in seen)) { if (!(inset in seen)) {
seen[inset] = 1; seen[inset] = 1;
score += csets[inset].length; score += csets[inset].length;
} else if(!(c in other)) { } else if (!(c in other)) {
score += 1; score += 1;
other[c] = 1; other[c] = 1;
} }
if(inset != lastset) { if (inset != lastset) {
score += 1; score += 1;
lastset = inset; lastset = inset;
} }
} }
var entropy = mystring.length * Math.log(score) / 0.6931471805599453; var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
return Math.round(entropy * 100) / 100 return Math.round(entropy * 100) / 100;
}, },
validate_entropy: function(myfield, req_entropy) { validate_entropy: function (myfield, req_entropy) {
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy'); if (!web2py.isUndefined(myfield.data('w2p_entropy'))) req_entropy = myfield.data('w2p_entropy');
var validator = function() { var validator = function () {
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy; var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
var r = 0, var r = 0,
g = 0, g = 0,
b = 0, b = 0,
rs = function(x) { rs = function (x) {
return Math.round(x * 15).toString(16) return Math.round(x * 15).toString(16);
}; };
if(v <= 0.5) { if (v <= 0.5) {
r = 1.0; r = 1.0;
g = 2.0 * v; g = 2.0 * v;
} else { } else {
@@ -456,17 +471,18 @@
} }
var color = '#' + rs(r) + rs(g) + rs(b); var color = '#' + rs(r) + rs(g) + rs(b);
myfield.css('background-color', color); myfield.css('background-color', color);
entropy_callback = myfield.data('entropy_callback'); var entropy_callback = myfield.data('entropy_callback');
if(entropy_callback) entropy_callback(v); if (entropy_callback) entropy_callback(v);
} };
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check'); if (!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator)
.addClass('entropy_check');
}, },
web2py_websocket: function(url, onmessage, onopen, onclose) { web2py_websocket: function (url, onmessage, onopen, onclose) {
if("WebSocket" in window) { if ('WebSocket' in window) {
var ws = new WebSocket(url); var ws = new WebSocket(url);
ws.onopen = onopen ? onopen : (function() {}); ws.onopen = onopen ? onopen : (function () {});
ws.onmessage = onmessage; ws.onmessage = onmessage;
ws.onclose = onclose ? onclose : (function() {}); ws.onclose = onclose ? onclose : (function () {});
return true; /* supported */ return true; /* supported */
} else return false; /* not supported */ } else return false; /* not supported */
}, },
@@ -478,7 +494,7 @@
/* Form input elements re-enabled after form submission */ /* Form input elements re-enabled after form submission */
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled', enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
/* Triggers an event on an element and returns false if the event result is false */ /* Triggers an event on an element and returns false if the event result is false */
fire: function(obj, type, data, target) { fire: function (obj, type, data, target) {
var event = $.Event(type, { var event = $.Event(type, {
'containerTarget': $('#' + target)[0] 'containerTarget': $('#' + target)[0]
}); });
@@ -486,45 +502,50 @@
return event.result !== false; return event.result !== false;
}, },
/* Helper function, needed to provide consistent behavior in IE */ /* Helper function, needed to provide consistent behavior in IE */
stopEverything: function(e) { stopEverything: function (e) {
$(e.target).trigger('w2p:everythingStopped'); $(e.target).trigger('w2p:everythingStopped');
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}, },
confirm: function(message) { confirm: function (message) {
return confirm(message); return confirm(message);
}, },
/* replace element's html with the 'data-disable-with' after storing original html /* replace element's html with the 'data-disable-with' after storing original html
* and prevent clicking on it */ * and prevent clicking on it */
disableElement: function(el) { disableElement: function (el) {
if (!web2py.isUndefined(el.data('w2p_disable'))) {
return false;
}
el.addClass('disabled'); el.addClass('disabled');
var method = el.is('input') ? 'val' : 'html'; var method = el.is('input') ? 'val' : 'html';
//method = el.attr('name') ? 'html' : 'val'; //method = el.attr('name') ? 'html' : 'val';
var disable_with_message = (typeof w2p_ajax_disable_with_message != 'undefined') ? w2p_ajax_disable_with_message : "Working..."; var disable_with_message = (!web2py.isUndefined(w2p_ajax_disable_with_message)) ?
w2p_ajax_disable_with_message : 'Working...';
/*store enabled state if not already disabled */ /*store enabled state if not already disabled */
if(el.data('w2p_enable_with') === undefined) { if (web2py.isUndefined(el.data('w2p_enable_with'))) {
el.data('w2p_enable_with', el[method]()); el.data('w2p_enable_with', el[method]());
} }
/*if you don't want to see "working..." on buttons, replace the following /*if you don't want to see "working..." on buttons, replace the following
* two lines with this one * two lines with this one
* el.data('w2p_disable_with', el[method]()); * el.data('w2p_disable_with', el[method]());
*/ */
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) { if ((el.data('w2p_disable_with') == 'default') || (web2py.isUndefined(el.data(
'w2p_disable_with')))) {
el.data('w2p_disable_with', disable_with_message); el.data('w2p_disable_with', disable_with_message);
} }
/* set to disabled state*/ /* set to disabled state*/
el[method](el.data('w2p_disable_with')); el[method](el.data('w2p_disable_with'));
el.bind('click.w2pDisable', function(e) { /* prevent further clicking*/ el.bind('click.w2pDisable', function (e) { /* prevent further clicking*/
return web2py.stopEverything(e); return web2py.stopEverything(e);
}); });
}, },
/* restore element to its original state which was disabled by 'disableElement' above*/ /* restore element to its original state which was disabled by 'disableElement' above*/
enableElement: function(el) { enableElement: function (el) {
var method = el.is('input') ? 'val' : 'html'; var method = el.is('input') ? 'val' : 'html';
if(el.data('w2p_enable_with') !== undefined) { if (!web2py.isUndefined(el.data('w2p_enable_with'))) {
/* set to old enabled state */ /* set to old enabled state */
el[method](el.data('w2p_enable_with')); el[method](el.data('w2p_enable_with'));
el.removeData('w2p_enable_with'); el.removeData('w2p_enable_with');
@@ -533,47 +554,47 @@
el.unbind('click.w2pDisable'); el.unbind('click.w2pDisable');
}, },
/*convenience wrapper, internal use only */ /*convenience wrapper, internal use only */
simple_component: function(action, target, element) { simple_component: function (action, target, element) {
web2py.component(action, target, 0, 1, element); web2py.component(action, target, 0, 1, element);
}, },
/*helper for flash messages*/ /*helper for flash messages*/
flash: function(message, status) { flash: function (message, status) {
var flash = $('.w2p_flash'); var flash = $('.w2p_flash');
web2py.hide_flash(); web2py.hide_flash();
flash.html(message).addClass(status); flash.html(message).addClass(status);
if(flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown(); if (flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown();
}, },
hide_flash: function() { hide_flash: function () {
$('.w2p_flash').fadeOut(0).html(''); $('.w2p_flash').fadeOut(0).html('');
}, },
show_if_handler: function(target) { show_if_handler: function (target) {
var triggers = {}; var triggers = {};
var show_if = function() { var show_if = function () {
var t = $(this); var t = $(this);
var id = t.attr('id'); var id = t.attr('id');
t.attr('value', t.val()); t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) { for (var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target); var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target); var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown(); if (t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide(); else tr.hide();
} }
}; };
$('[data-show-trigger]', target).each(function() { $('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger'); var name = $(this).attr('data-show-trigger');
// The field exists only when creating/editing a row // The field exists only when creating/editing a row
if($('#' + name).length) { if ($('#' + name).length) {
if(!triggers[name]) triggers[name] = []; if (!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id')); triggers[name].push($(this).attr('id'));
} }
}); });
for(var name in triggers) { for (var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if); $('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target)); show_if.call($('#' + name, target));
}; }
}, },
component_handler: function(target) { component_handler: function (target) {
$('div[data-w2p_remote]', target).each(function() { $('div[data-w2p_remote]', target).each(function () {
var remote, times, timeout, target; var remote, times, timeout, target;
var el = $(this); var el = $(this);
remote = el.data('w2p_remote'); remote = el.data('w2p_remote');
@@ -581,9 +602,9 @@
timeout = el.data('w2p_timeout'); timeout = el.data('w2p_timeout');
target = el.attr('id'); target = el.attr('id');
web2py.component(remote, target, timeout, times, $(this)); web2py.component(remote, target, timeout, times, $(this));
}) });
}, },
a_handler: function(el, e) { a_handler: function (el, e) {
e.preventDefault(); e.preventDefault();
var method = el.data('w2p_method'); var method = el.data('w2p_method');
var action = el.attr('href'); var action = el.attr('href');
@@ -591,55 +612,56 @@
var confirm_message = el.data('w2p_confirm'); var confirm_message = el.data('w2p_confirm');
var pre_call = el.data('w2p_pre_call'); var pre_call = el.data('w2p_pre_call');
if(pre_call != undefined) { if (!web2py.isUndefined(pre_call)) {
eval(pre_call); eval(pre_call);
} }
if(confirm_message) { if (confirm_message) {
if(confirm_message == 'default') if (confirm_message == 'default') {
confirm_message = w2p_ajax_confirm_message || confirm_message = w2p_ajax_confirm_message ||
'Are you sure you want to delete this object?'; 'Are you sure you want to delete this object?';
if(!web2py.confirm(confirm_message)) { }
if (!web2py.confirm(confirm_message)) {
web2py.stopEverything(e); web2py.stopEverything(e);
return; return;
} }
} }
if(target == undefined) { if (web2py.isUndefined(target)) {
if(method == 'GET') { if (method == 'GET') {
web2py.ajax_page('get', action, [], '', el); web2py.ajax_page('get', action, [], '', el);
} else if(method == 'POST') { } else if (method == 'POST') {
web2py.ajax_page('post', action, [], '', el); web2py.ajax_page('post', action, [], '', el);
} }
} else { } else {
if(method == 'GET') { if (method == 'GET') {
web2py.ajax_page('get', action, [], target, el); web2py.ajax_page('get', action, [], target, el);
} else if(method == 'POST') { } else if (method == 'POST') {
web2py.ajax_page('post', action, [], target, el); web2py.ajax_page('post', action, [], target, el);
} }
} }
}, },
a_handlers: function() { a_handlers: function () {
var el = $(document); var el = $(document);
el.on('click', 'a[data-w2p_method]', function(e) { el.on('click', 'a[data-w2p_method]', function (e) {
web2py.a_handler($(this), e); web2py.a_handler($(this), e);
}); });
/* removal of element should happen only on success */ /* removal of element should happen only on success */
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function(e) { el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function () {
var el = $(this); var el = $(this);
var toremove = el.data('w2p_remove'); var toremove = el.data('w2p_remove');
if(toremove != undefined) { if (!web2py.isUndefined(toremove)) {
toremove = el.closest(toremove); toremove = el.closest(toremove);
if(!toremove.length) { if (!toremove.length) {
/*this enables removal of whatever selector if a closest is not found */ /*this enables removal of whatever selector if a closest is not found */
toremove = $(toremove); toremove = $(toremove);
} }
toremove.remove(); toremove.remove();
} }
}); });
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function(e) { el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function () {
web2py.disableElement($(this)); web2py.disableElement($(this));
}); });
/*re-enable click on completion*/ /*re-enable click on completion*/
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function(e) { el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function () {
web2py.enableElement($(this)); web2py.enableElement($(this));
}); });
}, },
@@ -648,15 +670,19 @@
- Replaces element text with value of 'data-disable-with' attribute - Replaces element text with value of 'data-disable-with' attribute
- Sets disabled property to true - Sets disabled property to true
*/ */
disableFormElements: function(form) { disableFormElements: function (form) {
form.find(web2py.disableSelector).each(function() { form.find(web2py.disableSelector).each(function () {
var element = $(this), var element = $(this),
method = element.is('button') ? 'html' : 'val'; method = element.is('button') ? 'html' : 'val';
var disable_with = element.data('w2p_disable_with'); var disable_with = element.data('w2p_disable_with');
if(disable_with == undefined) { var disable = element.data('w2p_disable');
element.data('w2p_disable_with', element[method]()) if (!web2py.isUndefined(disable)) {
return false;
} }
if(element.data('w2p_enable_with') === undefined) { if (web2py.isUndefined(disable_with)) {
element.data('w2p_disable_with', element[method]());
}
if (web2py.isUndefined(element.data('w2p_enable_with'))) {
element.data('w2p_enable_with', element[method]()); element.data('w2p_enable_with', element[method]());
} }
element[method](element.data('w2p_disable_with')); element[method](element.data('w2p_disable_with'));
@@ -668,50 +694,50 @@
- Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`) - Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`)
- Sets disabled property to false - Sets disabled property to false
*/ */
enableFormElements: function(form) { enableFormElements: function (form) {
form.find(web2py.enableSelector).each(function() { form.find(web2py.enableSelector).each(function () {
var element = $(this), var element = $(this),
method = element.is('button') ? 'html' : 'val'; method = element.is('button') ? 'html' : 'val';
if(element.data('w2p_enable_with')) { if (element.data('w2p_enable_with')) {
element[method](element.data('w2p_enable_with')); element[method](element.data('w2p_enable_with'));
element.removeData('w2p_enable_with'); element.removeData('w2p_enable_with');
} }
element.prop('disabled', false); element.prop('disabled', false);
}); });
}, },
form_handlers: function() { form_handlers: function () {
var el = $(document); var el = $(document);
el.on('ajax:beforeSend', 'form[data-w2p_target]', function(e) { el.on('ajax:beforeSend', 'form[data-w2p_target]', function () {
web2py.disableFormElements($(this)); web2py.disableFormElements($(this));
}); });
el.on('ajax:complete', 'form[data-w2p_target]', function(e) { el.on('ajax:complete', 'form[data-w2p_target]', function () {
web2py.enableFormElements($(this)); web2py.enableFormElements($(this));
}); });
}, },
/* Invalidate and force reload of a web2py component /* Invalidate and force reload of a web2py component
*/ */
invalidate: function(target) { invalidate: function (target) {
$('div[data-w2p_remote]', target).each(function() { $('div[data-w2p_remote]', target).each(function () {
var el = $('#' + $(this).attr('id')).get(0); var el = $('#' + $(this).attr('id')).get(0);
if(el.timing !== undefined) { // Block triggering regular routines if (!web2py.isUndefined(el.timing)) { // Block triggering regular routines
clearInterval(el.timing); clearInterval(el.timing);
} }
}); });
$.web2py.component_handler(target); $.web2py.component_handler(target);
}, },
main_hook: function() { main_hook: function () {
var flash = $('.w2p_flash'); var flash = $('.w2p_flash');
flash.hide(); flash.hide();
if(flash.html()) web2py.flash(flash.html()); if (flash.html()) web2py.flash(flash.html());
web2py.ajax_init(document); web2py.ajax_init(document);
web2py.event_handlers(); web2py.event_handlers();
web2py.a_handlers(); web2py.a_handlers();
web2py.form_handlers(); web2py.form_handlers();
} }
} };
/*end of functions */ /*end of functions */
/*main hook*/ /*main hook*/
$(function() { $(function () {
web2py.main_hook(); web2py.main_hook();
}); });