web2py.js with no inline code, thanks Niphlod (this upgrade required upgrading web2py.js
This commit is contained in:
@@ -30,7 +30,7 @@ update:
|
|||||||
echo "remember that pymysql was tweaked"
|
echo "remember that pymysql was tweaked"
|
||||||
src:
|
src:
|
||||||
### Use semantic versioning
|
### Use semantic versioning
|
||||||
echo 'Version 2.5.1-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
echo 'Version 2.6.0-development+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||||
### rm -f all junk files
|
### rm -f all junk files
|
||||||
make clean
|
make clean
|
||||||
### clean up baisc apps
|
### clean up baisc apps
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Version 2.5.1-stable+timestamp.2013.06.26.04.01.26
|
Version 2.6.0-development+timestamp.2013.06.26.05.11.38
|
||||||
|
|||||||
@@ -1,242 +1,617 @@
|
|||||||
function popup(url) {
|
(function ($, undefined) {
|
||||||
newwindow=window.open(url,'name','height=400,width=600');
|
/*
|
||||||
if (window.focus) newwindow.focus();
|
* Unobtrusive scripting adapter for jQuery, largely taken from
|
||||||
return false;
|
* the wonderful https://github.com/rails/jquery-ujs
|
||||||
}
|
*
|
||||||
function collapse(id) { jQuery('#'+id).slideToggle(); }
|
*
|
||||||
function fade(id,value) { if(value>0) jQuery('#'+id).hide().fadeIn('slow'); else jQuery('#'+id).show().fadeOut('slow'); }
|
* Released under the MIT license
|
||||||
function ajax(u,s,t) {
|
*
|
||||||
query = '';
|
*/
|
||||||
if (typeof s == "string") {
|
|
||||||
d = jQuery(s).serialize();
|
String.prototype.reverse = function () {
|
||||||
if(d){ query = d; }
|
return this.split('').reverse().join('');
|
||||||
} else {
|
};
|
||||||
|
var web2py;
|
||||||
|
|
||||||
|
$.web2py = web2py = {
|
||||||
|
|
||||||
|
popup: function (url) {
|
||||||
|
newwindow = window.open(url, 'name', 'height=400,width=600');
|
||||||
|
if(window.focus) newwindow.focus();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
collapse: function () {
|
||||||
|
$('#' + id).slideToggle();
|
||||||
|
},
|
||||||
|
fade: function (id, value) {
|
||||||
|
if(value > 0) $('#' + id).hide().fadeIn('slow');
|
||||||
|
else $('#' + id).show().fadeOut('slow');
|
||||||
|
},
|
||||||
|
ajax: function (u, s, t) {
|
||||||
|
query = '';
|
||||||
|
if(typeof s == "string") {
|
||||||
|
d = $(s).serialize();
|
||||||
|
if(d) {
|
||||||
|
query = d;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
pcs = [];
|
pcs = [];
|
||||||
if (s != null && s != undefined) for(i=0; i<s.length; i++) {
|
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
|
||||||
q = jQuery("[name="+s[i]+"]").serialize();
|
q = $("[name=" + s[i] + "]").serialize();
|
||||||
if(q){pcs.push(q);}
|
if(q) {
|
||||||
|
pcs.push(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pcs.length > 0) {
|
||||||
|
query = pcs.join("&");
|
||||||
}
|
}
|
||||||
if (pcs.length>0){query = pcs.join("&");}
|
|
||||||
}
|
|
||||||
jQuery.ajax({type: "POST", url: u, data: query, success: function(msg) { if(t) { if(t==':eval') eval(msg); else if(typeof t=='string') jQuery("#"+t).html(msg); else t(msg); } } });
|
|
||||||
}
|
|
||||||
|
|
||||||
String.prototype.reverse = function () { return this.split('').reverse().join('');};
|
|
||||||
function web2py_ajax_fields(target) {
|
|
||||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
|
||||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
|
||||||
jQuery("input.date",target).each(function() {Calendar.setup({inputField:this, ifFormat:date_format, showsTime:false });});
|
|
||||||
jQuery("input.datetime",target).each(function() {Calendar.setup({inputField:this, ifFormat:datetime_format, showsTime: true, timeFormat: "24" });});
|
|
||||||
jQuery("input.time",target).each(function(){jQuery(this).timeEntry();});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function web2py_ajax_init(target) {
|
|
||||||
jQuery('.hidden', target).hide();
|
|
||||||
jQuery('.error', target).hide().slideDown('slow');
|
|
||||||
web2py_ajax_fields(target);
|
|
||||||
web2py_show_if(target);
|
|
||||||
};
|
|
||||||
|
|
||||||
function web2py_event_handlers() {
|
|
||||||
var doc = jQuery(document)
|
|
||||||
doc.on('click', '.flash', function(e){var t=jQuery(this); if(t.css('top')=='0px') t.slideUp('slow'); else t.fadeOut(); e.preventDefault();});
|
|
||||||
doc.on('keyup', 'input.integer', function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});
|
|
||||||
doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();});
|
|
||||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
|
||||||
doc.on('click', "input[type='checkbox'].delete", function(){if(this.checked) if(!confirm(confirm_message)) this.checked=false;});
|
|
||||||
|
|
||||||
doc.ajaxSuccess(function(e, xhr) {
|
|
||||||
var redirect=xhr.getResponseHeader('web2py-redirect-location');
|
|
||||||
var command=xhr.getResponseHeader('web2py-component-command');
|
|
||||||
var flash=xhr.getResponseHeader('web2py-component-flash');
|
|
||||||
if (redirect !== null) {
|
|
||||||
window.location = redirect;
|
|
||||||
};
|
|
||||||
if(command !== null){
|
|
||||||
eval(decodeURIComponent(command));
|
|
||||||
}
|
|
||||||
if(flash) {
|
|
||||||
jQuery('.flash')
|
|
||||||
.html(decodeURIComponent(flash))
|
|
||||||
.append('<span id="closeflash">×</span>')
|
|
||||||
.slideDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
doc.ajaxError(function(e, xhr, settings, exception) {
|
|
||||||
doc.off('click', '.flash')
|
|
||||||
switch(xhr.status){
|
|
||||||
case 500:
|
|
||||||
$('.flash').html(ajax_error_500).slideDown();
|
|
||||||
}
|
}
|
||||||
});
|
$.ajax({
|
||||||
};
|
type: "POST",
|
||||||
|
url: u,
|
||||||
jQuery(function() {
|
data: query,
|
||||||
var flash = jQuery('.flash');
|
success: function (msg) {
|
||||||
flash.hide();
|
if(t) {
|
||||||
if(flash.html()) flash.append('<span id="closeflash">×</span>').slideDown();
|
if(t == ':eval') eval(msg);
|
||||||
web2py_ajax_init(document);
|
else if(typeof t == 'string') $("#" + t).html(msg);
|
||||||
web2py_event_handlers();
|
else t(msg);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
function web2py_trap_form(action,target) {
|
|
||||||
jQuery('#'+target+' form').each(function(i){
|
|
||||||
var form=jQuery(this);
|
|
||||||
if(!form.hasClass('no_trap'))
|
|
||||||
form.submit(function(e){
|
|
||||||
jQuery('.flash').hide().html('');
|
|
||||||
web2py_ajax_page('post',action,form.serialize(),target);
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
}
|
ajax_fields: function (target) {
|
||||||
|
/*this attaches something to a newly loaded fragment/page
|
||||||
function web2py_trap_link(target) {
|
* Ideally all events should be bound to the document, so we can avoid calling
|
||||||
jQuery('#'+target+' a.w2p_trap').each(function(i){
|
* this over and over... all will be bound to the document
|
||||||
var link=jQuery(this);
|
*/
|
||||||
link.click(function(e) {
|
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||||
jQuery('.flash').hide().html('');
|
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||||
web2py_ajax_page('get',link.attr('href'),[],target);
|
$("input.date", target).each(function () {
|
||||||
e.preventDefault();
|
Calendar.setup({
|
||||||
});
|
inputField: this,
|
||||||
|
ifFormat: date_format,
|
||||||
|
showsTime: false
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
$("input.datetime", target).each(function () {
|
||||||
|
Calendar.setup({
|
||||||
|
inputField: this,
|
||||||
|
ifFormat: datetime_format,
|
||||||
|
showsTime: true,
|
||||||
|
timeFormat: "24"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$("input.time", target).each(function () {
|
||||||
|
$(this).timeEntry();
|
||||||
|
});
|
||||||
|
/*adds btn class to buttons*/
|
||||||
|
$('button', target).addClass('btn');
|
||||||
|
$('form input[type="submit"], form input[type="button"]', target).addClass('btn');
|
||||||
|
/*no more inline javascript for PasswordWidget*/
|
||||||
|
$('input[type=password][data-w2p_entropy]', target).each(function () {
|
||||||
|
web2py.validate_entropy($(this));
|
||||||
|
});
|
||||||
|
/*no more inline javascript for ListWidget*/
|
||||||
|
$('ul.w2p_list', target).each(function () {
|
||||||
|
function pe(ul, e) {
|
||||||
|
var new_line = ml(ul);
|
||||||
|
rel(ul);
|
||||||
|
if($(e.target).parent().is(':visible')) {
|
||||||
|
//make sure we didn't delete the element before we insert after
|
||||||
|
new_line.insertAfter($(e.target).parent());
|
||||||
|
} else {
|
||||||
|
//the line we clicked on was deleted, just add to end of list
|
||||||
|
new_line.appendTo(ul);
|
||||||
|
}
|
||||||
|
new_line.find(":text").focus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function web2py_ajax_page(method, action, data, target) {
|
function rl(ul, e) {
|
||||||
jQuery.ajax({'type':method, 'url':action, 'data':data,
|
if($(ul).children().length > 1) {
|
||||||
'beforeSend':function(xhr) {
|
//only remove if we have more than 1 item so the list is never empty
|
||||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
$(e.target).parent().remove();
|
||||||
xhr.setRequestHeader('web2py-component-element', target);},
|
}
|
||||||
'complete':function(xhr,text){
|
}
|
||||||
var html=xhr.responseText;
|
|
||||||
var content=xhr.getResponseHeader('web2py-component-content');
|
|
||||||
var t = jQuery('#'+target);
|
|
||||||
if(content=='prepend') t.prepend(html);
|
|
||||||
else if(content=='append') t.append(html);
|
|
||||||
else if(content!='hide') t.html(html);
|
|
||||||
web2py_trap_form(action,target);
|
|
||||||
web2py_trap_link(target);
|
|
||||||
web2py_ajax_init('#'+target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function web2py_component(action, target, timeout, times){
|
function ml(ul) {
|
||||||
jQuery(function(){
|
var line = $(ul).find("li:first").clone(true);
|
||||||
var jelement = jQuery("#" + target);
|
line.find(':text').val('');
|
||||||
var element = jelement.get(0);
|
return line;
|
||||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
}
|
||||||
jelement.reload = function (){
|
|
||||||
// Continue if times is Infinity or
|
function rel(ul) {
|
||||||
// the times limit is not reached
|
$(ul).find("li").each(function () {
|
||||||
if (element.reload_check()){
|
var trimmed = $.trim($(this.firstChild).val());
|
||||||
web2py_ajax_page('get', action, null, target);} }; // reload
|
if(trimmed == '') $(this).remove();
|
||||||
// Method to check timing limit
|
else $(this.firstChild).val(trimmed);
|
||||||
element.reload_check = function (){
|
});
|
||||||
if (jelement.hasClass('w2p_component_stop')) {clearInterval(this.timing);return false;}
|
}
|
||||||
if (this.reload_counter == Infinity){return true;}
|
var ul = this;
|
||||||
else {
|
$(ul).find(":text").after('<a href="#">+</a> <a href="#">-</a>').keypress(function (e) {
|
||||||
if (!isNaN(this.reload_counter)){
|
return(e.which == 13) ? pe(ul, e) : true;
|
||||||
this.reload_counter -= 1;
|
}).next().click(function (e) {
|
||||||
if (this.reload_counter < 0){
|
pe(ul, e);
|
||||||
if (!this.run_once){
|
e.preventDefault();
|
||||||
clearInterval(this.timing);
|
}).next().click(function (e) {
|
||||||
return false;
|
rl(ul, e);
|
||||||
}
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ajax_init: function (target) {
|
||||||
|
$('.hidden', target).hide();
|
||||||
|
web2py.manage_errors(target);
|
||||||
|
web2py.ajax_fields(target);
|
||||||
|
},
|
||||||
|
//manage errors in forms
|
||||||
|
manage_errors: function(target) {
|
||||||
|
$('.error', target).hide().slideDown('slow');
|
||||||
|
//$('.error', target).hide().fadeIn('slow');
|
||||||
|
},
|
||||||
|
event_handlers: function () {
|
||||||
|
/* This is called once for page
|
||||||
|
* Ideally it should bound all the things that are needed
|
||||||
|
*/
|
||||||
|
var doc = $(document);
|
||||||
|
doc.on('click', '.flash', function (e) {
|
||||||
|
console.log('das');
|
||||||
|
var t = $(this);
|
||||||
|
if(t.css('top') == '0px') t.slideUp('slow');
|
||||||
|
else t.fadeOut();
|
||||||
|
//if I want to display a clickable something
|
||||||
|
//inside flash, I should not be prevented to follow it
|
||||||
|
//e.preventDefault();
|
||||||
|
});
|
||||||
|
doc.on('keyup', 'input.integer', function () {
|
||||||
|
this.value = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
|
||||||
|
});
|
||||||
|
doc.on('keyup', 'input.double, input.decimal', function () {
|
||||||
|
this.value = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
|
||||||
|
});
|
||||||
|
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||||
|
doc.on('click', "input[type='checkbox'].delete", function () {
|
||||||
|
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.ajaxSuccess(function (e, xhr) {
|
||||||
|
var redirect = xhr.getResponseHeader('web2py-redirect-location');
|
||||||
|
var command = xhr.getResponseHeader('web2py-component-command');
|
||||||
|
var flash = xhr.getResponseHeader('web2py-component-flash');
|
||||||
|
if(redirect !== null) {
|
||||||
|
window.location = redirect;
|
||||||
|
};
|
||||||
|
if(command !== null) {
|
||||||
|
eval(decodeURIComponent(command));
|
||||||
|
}
|
||||||
|
if(flash) {
|
||||||
|
web2py.flash(decodeURIComponent(flash))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.ajaxError(function (e, xhr, settings, exception) {
|
||||||
|
//personally I don't like it.
|
||||||
|
//if there's an error it it flashed and can be removed
|
||||||
|
//as any other message
|
||||||
|
//doc.off('click', '.flash')
|
||||||
|
switch(xhr.status) {
|
||||||
|
case 500:
|
||||||
|
web2py.flash(ajax_error_500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
trap_form: function (action, target) {
|
||||||
|
$('#' + target + ' form').each(function (i) {
|
||||||
|
var form = $(this);
|
||||||
|
form.attr('data-w2p_target', target);
|
||||||
|
if(!form.hasClass('no_trap')) {
|
||||||
|
//should be there by default ?
|
||||||
|
form.find('input[type=submit]').attr('data-w2p_disable_with', 'Working...');
|
||||||
|
form.submit(function (e) {
|
||||||
|
web2py.hide_flash();
|
||||||
|
web2py.ajax_page('post', action, form.serialize(), target, form);
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
trap_link: function (target) {
|
||||||
|
$('#' + target + ' a.w2p_trap').each(function (i) {
|
||||||
|
var link = $(this);
|
||||||
|
link.click(function (e) {
|
||||||
|
web2py.hide_flash();
|
||||||
|
web2py.ajax_page('get', link.attr('href'), [], target);
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ajax_page: function (method, action, data, target, element) {
|
||||||
|
//element is a new parameter, but should be put be put in front
|
||||||
|
if(element == undefined) element = $(document);
|
||||||
|
if(web2py.fire(element, 'ajax:before')) { //test a usecase, should stop here if returns false
|
||||||
|
$.ajax({
|
||||||
|
'type': method,
|
||||||
|
'url': action,
|
||||||
|
'data': data,
|
||||||
|
'beforeSend': function (xhr, settings) {
|
||||||
|
//added
|
||||||
|
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||||
|
xhr.setRequestHeader('web2py-component-element', target);
|
||||||
|
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings]); //test a usecase, should stop here if returns false
|
||||||
|
},
|
||||||
|
//added
|
||||||
|
'success': function (data, status, xhr) {
|
||||||
|
//bummer for form submissions....the element is not there after complete
|
||||||
|
//because it gets replaced by the new response....
|
||||||
|
element.trigger('ajax:success', [data, status, xhr]);
|
||||||
|
},
|
||||||
|
//added
|
||||||
|
'error': function (xhr, status, error) {
|
||||||
|
//bummer for form submissions....in addition to the element being not there after
|
||||||
|
//complete because it gets replaced by the new response, standard form
|
||||||
|
//handling just returns the same status code for good and bad
|
||||||
|
//form submissions (i.e. that triggered a validator error)
|
||||||
|
element.trigger('ajax:error', [xhr, status, error]);
|
||||||
|
},
|
||||||
|
'complete': function (xhr, status) {
|
||||||
|
element.trigger('ajax:complete', [xhr, status]);
|
||||||
|
var html = xhr.responseText;
|
||||||
|
var content = xhr.getResponseHeader('web2py-component-content');
|
||||||
|
var t = $('#' + target);
|
||||||
|
if(content == 'prepend') t.prepend(html);
|
||||||
|
else if(content == 'append') t.append(html);
|
||||||
|
else if(content != 'hide') t.html(html);
|
||||||
|
web2py.trap_form(action, target);
|
||||||
|
web2py.trap_link(target);
|
||||||
|
web2py.ajax_init('#' + target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: function (action, target, timeout, times, el) {
|
||||||
|
//element is a new parameter, but should be put in front
|
||||||
|
$(function () {
|
||||||
|
var jelement = $("#" + target);
|
||||||
|
var element = jelement.get(0);
|
||||||
|
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||||
|
element.reload = function () {
|
||||||
|
// Continue if times is Infinity or
|
||||||
|
// the times limit is not reached
|
||||||
|
if(this.reload_check()) {
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
|
}
|
||||||
|
}; // reload
|
||||||
|
// Method to check timing limit
|
||||||
|
element.reload_check = function () {
|
||||||
|
if(jelement.hasClass('w2p_component_stop')) {
|
||||||
|
clearInterval(this.timing);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(this.reload_counter == Infinity) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(!isNaN(this.reload_counter)) {
|
||||||
|
this.reload_counter -= 1;
|
||||||
|
if(this.reload_counter < 0) {
|
||||||
|
if(!this.run_once) {
|
||||||
|
clearInterval(this.timing);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else{return true;}
|
} else {
|
||||||
} }
|
return true;
|
||||||
return false;}; // reload check
|
}
|
||||||
if (!isNaN(timeout)){
|
}
|
||||||
element.timeout = timeout;
|
}
|
||||||
element.reload_counter = times;
|
return false;
|
||||||
if (times > 1){
|
}; // reload check
|
||||||
// Multiple or infinite reload
|
if(!isNaN(timeout)) {
|
||||||
// Run first iteration
|
element.timeout = timeout;
|
||||||
web2py_ajax_page('get', action, null, target);
|
element.reload_counter = times;
|
||||||
element.run_once = false;
|
if(times > 1) {
|
||||||
element.timing = setInterval(statement, timeout);
|
// Multiple or infinite reload
|
||||||
element.reload_counter -= 1;
|
// Run first iteration
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
|
element.run_once = false;
|
||||||
|
element.timing = setInterval(statement, timeout);
|
||||||
|
element.reload_counter -= 1;
|
||||||
|
} else if(times == 1) {
|
||||||
|
// Run once with timeout
|
||||||
|
element.run_once = true;
|
||||||
|
element.setTimeout = setTimeout;
|
||||||
|
element.timing = setTimeout(statement, timeout);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// run once (no timeout specified)
|
||||||
|
element.reload_counter = Infinity;
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
}
|
}
|
||||||
else if (times == 1) {
|
});
|
||||||
// Run once with timeout
|
},
|
||||||
element.run_once = true;
|
calc_entropy: function (mystring) {
|
||||||
element.setTimeout = setTimeout;
|
//calculate a simple entropy for a given string
|
||||||
element.timing = setTimeout(statement, timeout);
|
var csets = new Array(
|
||||||
|
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||||
|
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||||
|
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||||
|
var score = 0,
|
||||||
|
other = {}, seen = {}, lastset = null,
|
||||||
|
mystringlist = mystring.split('');
|
||||||
|
for(var i = 0; i < mystringlist.length; i++) { // classify this character
|
||||||
|
var c = mystringlist[i],
|
||||||
|
inset = 5;
|
||||||
|
for(var j = 0; j < csets.length; j++)
|
||||||
|
if(csets[j].indexOf(c) != -1) {
|
||||||
|
inset = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//calculate effect of character on alphabet size
|
||||||
|
if(!(inset in seen)) {
|
||||||
|
seen[inset] = 1;
|
||||||
|
score += csets[inset].length;
|
||||||
|
} else if(!(c in other)) {
|
||||||
|
score += 1;
|
||||||
|
other[c] = 1;
|
||||||
}
|
}
|
||||||
} else {
|
if(inset != lastset) {
|
||||||
// run once (no timeout specified)
|
score += 1;
|
||||||
element.reload_counter = Infinity;
|
lastset = inset;
|
||||||
web2py_ajax_page('get', action, null, target);
|
}
|
||||||
} }); }
|
}
|
||||||
|
var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
|
||||||
|
return Math.round(entropy * 100) / 100
|
||||||
|
},
|
||||||
|
validate_entropy: function (myfield, req_entropy) {
|
||||||
|
//added
|
||||||
|
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy');
|
||||||
|
var validator = function () {
|
||||||
|
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
|
||||||
|
var r = 0,
|
||||||
|
g = 0,
|
||||||
|
b = 0,
|
||||||
|
rs = function (x) {
|
||||||
|
return Math.round(x * 15).toString(16)
|
||||||
|
};
|
||||||
|
if(v <= 0.5) {
|
||||||
|
r = 1.0;
|
||||||
|
g = 2.0 * v;
|
||||||
|
} else {
|
||||||
|
r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
|
||||||
|
g = 1.0;
|
||||||
|
}
|
||||||
|
var color = '#' + rs(r) + rs(g) + rs(b);
|
||||||
|
myfield.css('background-color', color);
|
||||||
|
entropy_callback = myfield.data('entropy_callback');
|
||||||
|
if(entropy_callback) entropy_callback(v);
|
||||||
|
}
|
||||||
|
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||||
|
},
|
||||||
|
web2py_websocket: function (url, onmessage, onopen, onclose) {
|
||||||
|
if("WebSocket" in window) {
|
||||||
|
var ws = new WebSocket(url);
|
||||||
|
ws.onopen = onopen ? onopen : (function () {});
|
||||||
|
ws.onmessage = onmessage;
|
||||||
|
ws.onclose = onclose ? onclose : (function () {});
|
||||||
|
return true; // supported
|
||||||
|
} else return false; // not supported
|
||||||
|
},
|
||||||
|
/* new from here */
|
||||||
|
// Form input elements bound by jquery-ujs
|
||||||
|
formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
|
||||||
|
// Form input elements disabled during form submission
|
||||||
|
disableSelector: 'input, button, textarea, select',
|
||||||
|
// Form input elements re-enabled after form submission
|
||||||
|
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
|
||||||
|
// Triggers an event on an element and returns false if the event result is false
|
||||||
|
fire: function (obj, name, data) {
|
||||||
|
var event = $.Event(name);
|
||||||
|
obj.trigger(event, data);
|
||||||
|
return event.result !== false;
|
||||||
|
},
|
||||||
|
// Helper function, needed to provide consistent behavior in IE
|
||||||
|
stopEverything: function (e) {
|
||||||
|
$(e.target).trigger('w2p:everythingStopped');
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
confirm: function (message) {
|
||||||
|
return confirm(message);
|
||||||
|
},
|
||||||
|
// replace element's html with the 'data-disable-with' after storing original html
|
||||||
|
// and prevent clicking on it
|
||||||
|
disableElement: function (el) {
|
||||||
|
el.addClass('disabled');
|
||||||
|
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||||
|
// store enabled state
|
||||||
|
el.data('w2p:enable-with', el[method]);
|
||||||
|
/* little addition by default*/
|
||||||
|
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
|
||||||
|
el.data('w2p_disable_with', 'Working...');
|
||||||
|
}
|
||||||
|
// set to disabled state
|
||||||
|
el[method](el.data('w2p_disable_with'));
|
||||||
|
|
||||||
function web2py_websocket(url,onmessage,onopen,onclose) {
|
el.bind('click.w2pDisable', function (e) { // prevent further clicking
|
||||||
if ("WebSocket" in window) {
|
return web2py.stopEverything(e);
|
||||||
var ws = new WebSocket(url);
|
});
|
||||||
ws.onopen = onopen?onopen:(function(){});
|
},
|
||||||
ws.onmessage = onmessage;
|
|
||||||
ws.onclose = onclose?onclose:(function(){});
|
|
||||||
return true; // supported
|
|
||||||
} else return false; // not supported
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// restore element to its original state which was disabled by 'disableElement' above
|
||||||
|
enableElement: function (el) {
|
||||||
|
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||||
|
if(el.data('w2p:enable-with') !== undefined) {
|
||||||
|
// set to old enabled state
|
||||||
|
el[method](el.data('w2p:enable-with'));
|
||||||
|
el.removeData('w2p:enable-with'); // clean up cache
|
||||||
|
}
|
||||||
|
el.removeClass('disabled');
|
||||||
|
el.unbind('click.w2pDisable'); // enable element
|
||||||
|
},
|
||||||
|
//convenience wrapper, internal use only
|
||||||
|
simple_component: function (action, target, element) {
|
||||||
|
web2py.component(action, target, 0, 1, element);
|
||||||
|
},
|
||||||
|
//helper for flash messages
|
||||||
|
flash: function(message, status) {
|
||||||
|
var flash = $('.flash');
|
||||||
|
web2py.hide_flash();
|
||||||
|
flash.html(message).addClass(status);
|
||||||
|
if(flash.html()) flash.append('<span id="closeflash"> × </span>').slideDown();
|
||||||
|
},
|
||||||
|
hide_flash: function() {
|
||||||
|
$('.flash').hide().html('');
|
||||||
|
},
|
||||||
|
a_handler: function (el, e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var method = el.data('w2p_method');
|
||||||
|
var action = el.attr('href');
|
||||||
|
var target = el.data('w2p_target');
|
||||||
|
var confirm_message = el.data('w2p_confirm');
|
||||||
|
|
||||||
function web2py_calc_entropy(mystring) {
|
var pre_call = el.data('w2p_pre_call');
|
||||||
//calculate a simple entropy for a given string
|
if(pre_call != undefined) {
|
||||||
var csets = new Array(
|
eval(pre_call);
|
||||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
}
|
||||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
if(confirm_message != undefined) {
|
||||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
if(confirm_message == 'default') confirm_message = w2p_ajax_confirm_message || 'Are you sure you want to delete this object?';
|
||||||
var score = 0, other = {}, seen = {}, lastset = null, mystringlist = mystring.split('');
|
if(!web2py.confirm(confirm_message)) {
|
||||||
for (var i=0;i<mystringlist.length;i++) { // classify this character
|
web2py.stopEverything(e);
|
||||||
var c = mystringlist[i], inset=5;
|
return;
|
||||||
for(var j = 0; j<csets.length; j++)
|
}
|
||||||
if (csets[j].indexOf(c) != -1) {inset = j; break;}
|
}
|
||||||
//calculate effect of character on alphabet size
|
if(target == undefined) {
|
||||||
if(!(inset in seen)) {seen[inset] = 1;score += csets[inset].length;}
|
if(method == 'GET') {
|
||||||
else if (!(c in other)) {score += 1;other[c] = 1;}
|
web2py.simple_component(action, el.attr('id'), el); //not working with original
|
||||||
if (inset != lastset) {score += 1;lastset = inset;}
|
} else if(method == 'POST') {
|
||||||
}
|
//should be web2py.ajax(action, [], ''); but it's too simple
|
||||||
var entropy = mystring.length*Math.log(score)/0.6931471805599453;
|
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
||||||
return Math.round(entropy*100)/100
|
}
|
||||||
}
|
} else {
|
||||||
|
if(method == 'GET') {
|
||||||
|
web2py.simple_component(action, target, el);
|
||||||
|
} else if(method == 'POST') {
|
||||||
|
//should be web2py.ajax(action, [], target); but it's too simple
|
||||||
|
web2py.ajax_page('post', action, [], target, el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*this should happen only on ajaxsuccess
|
||||||
|
* and should block subsequent clicks until ajaxcomplete
|
||||||
|
* NB: introduce the first incompatibility because normally
|
||||||
|
* the element would be removed in either case
|
||||||
|
/* removal code moved to the ajax:success event - START
|
||||||
|
if(toremove != undefined) {
|
||||||
|
toremove = el.closest(toremove);
|
||||||
|
if(!toremove.length) {
|
||||||
|
//this enables removal of whatever selector if a closest is not found
|
||||||
|
toremove = $(toremove);
|
||||||
|
}
|
||||||
|
toremove.remove();
|
||||||
|
}
|
||||||
|
/* removal code moved to the ajax:success event - END */
|
||||||
|
},
|
||||||
|
a_handlers: function () {
|
||||||
|
var el = $(document);
|
||||||
|
el.on('click', 'a[data-w2p_method]', function (e) {
|
||||||
|
web2py.a_handler($(this), e);
|
||||||
|
});
|
||||||
|
/* removal of element should happen only on success */
|
||||||
|
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function (e) {
|
||||||
|
var el = $(this);
|
||||||
|
var toremove = el.data('w2p_remove');
|
||||||
|
if(toremove != undefined) {
|
||||||
|
toremove = el.closest(toremove);
|
||||||
|
if(!toremove.length) {
|
||||||
|
//this enables removal of whatever selector if a closest is not found
|
||||||
|
toremove = $(toremove);
|
||||||
|
}
|
||||||
|
toremove.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||||
|
web2py.disableElement($(this));
|
||||||
|
});
|
||||||
|
/*re-enable click on completion*/
|
||||||
|
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||||
|
web2py.enableElement($(this));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/* Disables form elements:
|
||||||
|
- Caches element value in 'ujs:enable-with' data store
|
||||||
|
- Replaces element text with value of 'data-disable-with' attribute
|
||||||
|
- Sets disabled property to true
|
||||||
|
*/
|
||||||
|
disableFormElements: function(form) {
|
||||||
|
form.find(web2py.disableSelector).each(function() {
|
||||||
|
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||||
|
var disable_with = element.data('w2p_disable_with');
|
||||||
|
if (disable_with == undefined) {
|
||||||
|
element.data('w2p_disable_with', element[method]())
|
||||||
|
}
|
||||||
|
element.data('w2p:enable-with', element[method]());
|
||||||
|
element[method](element.data('w2p_disable_with'));
|
||||||
|
element.prop('disabled', true);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
function web2py_validate_entropy(myfield, req_entropy) {
|
/* Re-enables disabled form elements:
|
||||||
var validator = function () {
|
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
|
||||||
var v = (web2py_calc_entropy(myfield.val())||0)/req_entropy;
|
- Sets disabled property to false
|
||||||
var r=0,g=0,b=0,rs=function(x){return Math.round(x*15).toString(16)};
|
*/
|
||||||
if(v<=0.5) {r=1.0; g=2.0*v;}
|
enableFormElements: function(form) {
|
||||||
else {r=(1.0-2.0*(Math.max(v,0)-0.5)); g=1.0;}
|
form.find(web2py.enableSelector).each(function() {
|
||||||
var color = '#'+rs(r)+rs(g)+rs(b);
|
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||||
myfield.css('background-color',color);
|
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
|
||||||
entropy_callback = myfield.data('entropy_callback');
|
element.prop('disabled', false);
|
||||||
if(entropy_callback) entropy_callback(v);
|
});
|
||||||
}
|
},
|
||||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
form_handlers: function() {
|
||||||
}
|
var el = $(document);
|
||||||
|
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
|
||||||
function web2py_show_if(target) {
|
web2py.disableFormElements($(this));
|
||||||
var triggers = {};
|
});
|
||||||
var show_if = function () {
|
el.on('ajax:complete', 'form[data-w2p_target]', function (e) {
|
||||||
var t = jQuery(this);
|
web2py.enableFormElements($(this));
|
||||||
var id = t.attr('id');
|
});
|
||||||
t.attr('value', t.val());
|
|
||||||
for(var k = 0; k < triggers[id].length; k++) {
|
|
||||||
var dep = jQuery('#' + triggers[id][k], target);
|
|
||||||
var tr = jQuery('#' + triggers[id][k] + '__row', target);
|
|
||||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
|
||||||
else tr.hide();
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
jQuery('[data-show-trigger]', target).each(function () {
|
|
||||||
var name = jQuery(this).attr('data-show-trigger');
|
//end of functions
|
||||||
if(!triggers[name]) triggers[name] = [];
|
//main hook
|
||||||
triggers[name].push(jQuery(this).attr('id'));
|
$(function () {
|
||||||
});
|
var flash = $('.flash');
|
||||||
for(var name in triggers) {
|
flash.hide();
|
||||||
jQuery('#' + name, target).change(show_if).keyup(show_if);
|
if(flash.html()) web2py.flash(flash.html());
|
||||||
show_if.call(jQuery('#' + name, target));
|
web2py.ajax_init(document);
|
||||||
};
|
web2py.event_handlers();
|
||||||
}
|
web2py.a_handlers();
|
||||||
|
web2py.form_handlers();
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
/* compatibility code - start */
|
||||||
|
ajax = $.web2py.ajax;
|
||||||
|
web2py_component = $.web2py.component;
|
||||||
|
web2py_websocket = $.web2py.websocket;
|
||||||
|
web2py_ajax_page = $.web2py.ajax_page;
|
||||||
|
//needed for IS_STRONG(entropy)
|
||||||
|
web2py_validate_entropy = $.web2py.validate_entropy;
|
||||||
|
//needed for crud.search and SQLFORM.grid's search
|
||||||
|
web2py_ajax_fields = $.web2py.ajax_fields;
|
||||||
|
//used for LOAD(ajax=False)
|
||||||
|
web2py_trap_form = $.web2py.trap_form;
|
||||||
|
|
||||||
|
/*undocumented - rare*/
|
||||||
|
popup = $.web2py.popup;
|
||||||
|
collapse = $.web2py.collapse;
|
||||||
|
fade = $.web2py.fade;
|
||||||
|
|
||||||
|
/* internals - shouldn't be needed
|
||||||
|
|
||||||
|
web2py_ajax_init = $.web2py.ajax_init;
|
||||||
|
web2py_event_handlers = $.web2py.event_handlers;
|
||||||
|
|
||||||
|
web2py_trap_link = $.web2py.trap_link;
|
||||||
|
web2py_calc_entropy = $.web2py.calc_entropy;
|
||||||
|
*/
|
||||||
|
/* compatibility code - end*/
|
||||||
|
|||||||
@@ -1,242 +1,617 @@
|
|||||||
function popup(url) {
|
(function ($, undefined) {
|
||||||
newwindow=window.open(url,'name','height=400,width=600');
|
/*
|
||||||
if (window.focus) newwindow.focus();
|
* Unobtrusive scripting adapter for jQuery, largely taken from
|
||||||
return false;
|
* the wonderful https://github.com/rails/jquery-ujs
|
||||||
}
|
*
|
||||||
function collapse(id) { jQuery('#'+id).slideToggle(); }
|
*
|
||||||
function fade(id,value) { if(value>0) jQuery('#'+id).hide().fadeIn('slow'); else jQuery('#'+id).show().fadeOut('slow'); }
|
* Released under the MIT license
|
||||||
function ajax(u,s,t) {
|
*
|
||||||
query = '';
|
*/
|
||||||
if (typeof s == "string") {
|
|
||||||
d = jQuery(s).serialize();
|
String.prototype.reverse = function () {
|
||||||
if(d){ query = d; }
|
return this.split('').reverse().join('');
|
||||||
} else {
|
};
|
||||||
|
var web2py;
|
||||||
|
|
||||||
|
$.web2py = web2py = {
|
||||||
|
|
||||||
|
popup: function (url) {
|
||||||
|
newwindow = window.open(url, 'name', 'height=400,width=600');
|
||||||
|
if(window.focus) newwindow.focus();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
collapse: function () {
|
||||||
|
$('#' + id).slideToggle();
|
||||||
|
},
|
||||||
|
fade: function (id, value) {
|
||||||
|
if(value > 0) $('#' + id).hide().fadeIn('slow');
|
||||||
|
else $('#' + id).show().fadeOut('slow');
|
||||||
|
},
|
||||||
|
ajax: function (u, s, t) {
|
||||||
|
query = '';
|
||||||
|
if(typeof s == "string") {
|
||||||
|
d = $(s).serialize();
|
||||||
|
if(d) {
|
||||||
|
query = d;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
pcs = [];
|
pcs = [];
|
||||||
if (s != null && s != undefined) for(i=0; i<s.length; i++) {
|
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
|
||||||
q = jQuery("[name="+s[i]+"]").serialize();
|
q = $("[name=" + s[i] + "]").serialize();
|
||||||
if(q){pcs.push(q);}
|
if(q) {
|
||||||
|
pcs.push(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pcs.length > 0) {
|
||||||
|
query = pcs.join("&");
|
||||||
}
|
}
|
||||||
if (pcs.length>0){query = pcs.join("&");}
|
|
||||||
}
|
|
||||||
jQuery.ajax({type: "POST", url: u, data: query, success: function(msg) { if(t) { if(t==':eval') eval(msg); else if(typeof t=='string') jQuery("#"+t).html(msg); else t(msg); } } });
|
|
||||||
}
|
|
||||||
|
|
||||||
String.prototype.reverse = function () { return this.split('').reverse().join('');};
|
|
||||||
function web2py_ajax_fields(target) {
|
|
||||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
|
||||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
|
||||||
jQuery("input.date",target).each(function() {Calendar.setup({inputField:this, ifFormat:date_format, showsTime:false });});
|
|
||||||
jQuery("input.datetime",target).each(function() {Calendar.setup({inputField:this, ifFormat:datetime_format, showsTime: true, timeFormat: "24" });});
|
|
||||||
jQuery("input.time",target).each(function(){jQuery(this).timeEntry();});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function web2py_ajax_init(target) {
|
|
||||||
jQuery('.hidden', target).hide();
|
|
||||||
jQuery('.error', target).hide().slideDown('slow');
|
|
||||||
web2py_ajax_fields(target);
|
|
||||||
web2py_show_if(target);
|
|
||||||
};
|
|
||||||
|
|
||||||
function web2py_event_handlers() {
|
|
||||||
var doc = jQuery(document)
|
|
||||||
doc.on('click', '.flash', function(e){var t=jQuery(this); if(t.css('top')=='0px') t.slideUp('slow'); else t.fadeOut(); e.preventDefault();});
|
|
||||||
doc.on('keyup', 'input.integer', function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});
|
|
||||||
doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();});
|
|
||||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
|
||||||
doc.on('click', "input[type='checkbox'].delete", function(){if(this.checked) if(!confirm(confirm_message)) this.checked=false;});
|
|
||||||
|
|
||||||
doc.ajaxSuccess(function(e, xhr) {
|
|
||||||
var redirect=xhr.getResponseHeader('web2py-redirect-location');
|
|
||||||
var command=xhr.getResponseHeader('web2py-component-command');
|
|
||||||
var flash=xhr.getResponseHeader('web2py-component-flash');
|
|
||||||
if (redirect !== null) {
|
|
||||||
window.location = redirect;
|
|
||||||
};
|
|
||||||
if(command !== null){
|
|
||||||
eval(decodeURIComponent(command));
|
|
||||||
}
|
|
||||||
if(flash) {
|
|
||||||
jQuery('.flash')
|
|
||||||
.html(decodeURIComponent(flash))
|
|
||||||
.append('<span id="closeflash">×</span>')
|
|
||||||
.slideDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
doc.ajaxError(function(e, xhr, settings, exception) {
|
|
||||||
doc.off('click', '.flash')
|
|
||||||
switch(xhr.status){
|
|
||||||
case 500:
|
|
||||||
$('.flash').html(ajax_error_500).slideDown();
|
|
||||||
}
|
}
|
||||||
});
|
$.ajax({
|
||||||
};
|
type: "POST",
|
||||||
|
url: u,
|
||||||
jQuery(function() {
|
data: query,
|
||||||
var flash = jQuery('.flash');
|
success: function (msg) {
|
||||||
flash.hide();
|
if(t) {
|
||||||
if(flash.html()) flash.append('<span id="closeflash">×</span>').slideDown();
|
if(t == ':eval') eval(msg);
|
||||||
web2py_ajax_init(document);
|
else if(typeof t == 'string') $("#" + t).html(msg);
|
||||||
web2py_event_handlers();
|
else t(msg);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
function web2py_trap_form(action,target) {
|
|
||||||
jQuery('#'+target+' form').each(function(i){
|
|
||||||
var form=jQuery(this);
|
|
||||||
if(!form.hasClass('no_trap'))
|
|
||||||
form.submit(function(e){
|
|
||||||
jQuery('.flash').hide().html('');
|
|
||||||
web2py_ajax_page('post',action,form.serialize(),target);
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
}
|
ajax_fields: function (target) {
|
||||||
|
/*this attaches something to a newly loaded fragment/page
|
||||||
function web2py_trap_link(target) {
|
* Ideally all events should be bound to the document, so we can avoid calling
|
||||||
jQuery('#'+target+' a.w2p_trap').each(function(i){
|
* this over and over... all will be bound to the document
|
||||||
var link=jQuery(this);
|
*/
|
||||||
link.click(function(e) {
|
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||||
jQuery('.flash').hide().html('');
|
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||||
web2py_ajax_page('get',link.attr('href'),[],target);
|
$("input.date", target).each(function () {
|
||||||
e.preventDefault();
|
Calendar.setup({
|
||||||
});
|
inputField: this,
|
||||||
|
ifFormat: date_format,
|
||||||
|
showsTime: false
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
$("input.datetime", target).each(function () {
|
||||||
|
Calendar.setup({
|
||||||
|
inputField: this,
|
||||||
|
ifFormat: datetime_format,
|
||||||
|
showsTime: true,
|
||||||
|
timeFormat: "24"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$("input.time", target).each(function () {
|
||||||
|
$(this).timeEntry();
|
||||||
|
});
|
||||||
|
/*adds btn class to buttons*/
|
||||||
|
$('button', target).addClass('btn');
|
||||||
|
$('form input[type="submit"], form input[type="button"]', target).addClass('btn');
|
||||||
|
/*no more inline javascript for PasswordWidget*/
|
||||||
|
$('input[type=password][data-w2p_entropy]', target).each(function () {
|
||||||
|
web2py.validate_entropy($(this));
|
||||||
|
});
|
||||||
|
/*no more inline javascript for ListWidget*/
|
||||||
|
$('ul.w2p_list', target).each(function () {
|
||||||
|
function pe(ul, e) {
|
||||||
|
var new_line = ml(ul);
|
||||||
|
rel(ul);
|
||||||
|
if($(e.target).parent().is(':visible')) {
|
||||||
|
//make sure we didn't delete the element before we insert after
|
||||||
|
new_line.insertAfter($(e.target).parent());
|
||||||
|
} else {
|
||||||
|
//the line we clicked on was deleted, just add to end of list
|
||||||
|
new_line.appendTo(ul);
|
||||||
|
}
|
||||||
|
new_line.find(":text").focus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function web2py_ajax_page(method, action, data, target) {
|
function rl(ul, e) {
|
||||||
jQuery.ajax({'type':method, 'url':action, 'data':data,
|
if($(ul).children().length > 1) {
|
||||||
'beforeSend':function(xhr) {
|
//only remove if we have more than 1 item so the list is never empty
|
||||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
$(e.target).parent().remove();
|
||||||
xhr.setRequestHeader('web2py-component-element', target);},
|
}
|
||||||
'complete':function(xhr,text){
|
}
|
||||||
var html=xhr.responseText;
|
|
||||||
var content=xhr.getResponseHeader('web2py-component-content');
|
|
||||||
var t = jQuery('#'+target);
|
|
||||||
if(content=='prepend') t.prepend(html);
|
|
||||||
else if(content=='append') t.append(html);
|
|
||||||
else if(content!='hide') t.html(html);
|
|
||||||
web2py_trap_form(action,target);
|
|
||||||
web2py_trap_link(target);
|
|
||||||
web2py_ajax_init('#'+target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function web2py_component(action, target, timeout, times){
|
function ml(ul) {
|
||||||
jQuery(function(){
|
var line = $(ul).find("li:first").clone(true);
|
||||||
var jelement = jQuery("#" + target);
|
line.find(':text').val('');
|
||||||
var element = jelement.get(0);
|
return line;
|
||||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
}
|
||||||
jelement.reload = function (){
|
|
||||||
// Continue if times is Infinity or
|
function rel(ul) {
|
||||||
// the times limit is not reached
|
$(ul).find("li").each(function () {
|
||||||
if (element.reload_check()){
|
var trimmed = $.trim($(this.firstChild).val());
|
||||||
web2py_ajax_page('get', action, null, target);} }; // reload
|
if(trimmed == '') $(this).remove();
|
||||||
// Method to check timing limit
|
else $(this.firstChild).val(trimmed);
|
||||||
element.reload_check = function (){
|
});
|
||||||
if (jelement.hasClass('w2p_component_stop')) {clearInterval(this.timing);return false;}
|
}
|
||||||
if (this.reload_counter == Infinity){return true;}
|
var ul = this;
|
||||||
else {
|
$(ul).find(":text").after('<a href="#">+</a> <a href="#">-</a>').keypress(function (e) {
|
||||||
if (!isNaN(this.reload_counter)){
|
return(e.which == 13) ? pe(ul, e) : true;
|
||||||
this.reload_counter -= 1;
|
}).next().click(function (e) {
|
||||||
if (this.reload_counter < 0){
|
pe(ul, e);
|
||||||
if (!this.run_once){
|
e.preventDefault();
|
||||||
clearInterval(this.timing);
|
}).next().click(function (e) {
|
||||||
return false;
|
rl(ul, e);
|
||||||
}
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ajax_init: function (target) {
|
||||||
|
$('.hidden', target).hide();
|
||||||
|
web2py.manage_errors(target);
|
||||||
|
web2py.ajax_fields(target);
|
||||||
|
},
|
||||||
|
//manage errors in forms
|
||||||
|
manage_errors: function(target) {
|
||||||
|
$('.error', target).hide().slideDown('slow');
|
||||||
|
//$('.error', target).hide().fadeIn('slow');
|
||||||
|
},
|
||||||
|
event_handlers: function () {
|
||||||
|
/* This is called once for page
|
||||||
|
* Ideally it should bound all the things that are needed
|
||||||
|
*/
|
||||||
|
var doc = $(document);
|
||||||
|
doc.on('click', '.flash', function (e) {
|
||||||
|
console.log('das');
|
||||||
|
var t = $(this);
|
||||||
|
if(t.css('top') == '0px') t.slideUp('slow');
|
||||||
|
else t.fadeOut();
|
||||||
|
//if I want to display a clickable something
|
||||||
|
//inside flash, I should not be prevented to follow it
|
||||||
|
//e.preventDefault();
|
||||||
|
});
|
||||||
|
doc.on('keyup', 'input.integer', function () {
|
||||||
|
this.value = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
|
||||||
|
});
|
||||||
|
doc.on('keyup', 'input.double, input.decimal', function () {
|
||||||
|
this.value = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
|
||||||
|
});
|
||||||
|
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||||
|
doc.on('click', "input[type='checkbox'].delete", function () {
|
||||||
|
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.ajaxSuccess(function (e, xhr) {
|
||||||
|
var redirect = xhr.getResponseHeader('web2py-redirect-location');
|
||||||
|
var command = xhr.getResponseHeader('web2py-component-command');
|
||||||
|
var flash = xhr.getResponseHeader('web2py-component-flash');
|
||||||
|
if(redirect !== null) {
|
||||||
|
window.location = redirect;
|
||||||
|
};
|
||||||
|
if(command !== null) {
|
||||||
|
eval(decodeURIComponent(command));
|
||||||
|
}
|
||||||
|
if(flash) {
|
||||||
|
web2py.flash(decodeURIComponent(flash))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.ajaxError(function (e, xhr, settings, exception) {
|
||||||
|
//personally I don't like it.
|
||||||
|
//if there's an error it it flashed and can be removed
|
||||||
|
//as any other message
|
||||||
|
//doc.off('click', '.flash')
|
||||||
|
switch(xhr.status) {
|
||||||
|
case 500:
|
||||||
|
web2py.flash(ajax_error_500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
trap_form: function (action, target) {
|
||||||
|
$('#' + target + ' form').each(function (i) {
|
||||||
|
var form = $(this);
|
||||||
|
form.attr('data-w2p_target', target);
|
||||||
|
if(!form.hasClass('no_trap')) {
|
||||||
|
//should be there by default ?
|
||||||
|
form.find('input[type=submit]').attr('data-w2p_disable_with', 'Working...');
|
||||||
|
form.submit(function (e) {
|
||||||
|
web2py.hide_flash();
|
||||||
|
web2py.ajax_page('post', action, form.serialize(), target, form);
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
trap_link: function (target) {
|
||||||
|
$('#' + target + ' a.w2p_trap').each(function (i) {
|
||||||
|
var link = $(this);
|
||||||
|
link.click(function (e) {
|
||||||
|
web2py.hide_flash();
|
||||||
|
web2py.ajax_page('get', link.attr('href'), [], target);
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ajax_page: function (method, action, data, target, element) {
|
||||||
|
//element is a new parameter, but should be put be put in front
|
||||||
|
if(element == undefined) element = $(document);
|
||||||
|
if(web2py.fire(element, 'ajax:before')) { //test a usecase, should stop here if returns false
|
||||||
|
$.ajax({
|
||||||
|
'type': method,
|
||||||
|
'url': action,
|
||||||
|
'data': data,
|
||||||
|
'beforeSend': function (xhr, settings) {
|
||||||
|
//added
|
||||||
|
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||||
|
xhr.setRequestHeader('web2py-component-element', target);
|
||||||
|
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings]); //test a usecase, should stop here if returns false
|
||||||
|
},
|
||||||
|
//added
|
||||||
|
'success': function (data, status, xhr) {
|
||||||
|
//bummer for form submissions....the element is not there after complete
|
||||||
|
//because it gets replaced by the new response....
|
||||||
|
element.trigger('ajax:success', [data, status, xhr]);
|
||||||
|
},
|
||||||
|
//added
|
||||||
|
'error': function (xhr, status, error) {
|
||||||
|
//bummer for form submissions....in addition to the element being not there after
|
||||||
|
//complete because it gets replaced by the new response, standard form
|
||||||
|
//handling just returns the same status code for good and bad
|
||||||
|
//form submissions (i.e. that triggered a validator error)
|
||||||
|
element.trigger('ajax:error', [xhr, status, error]);
|
||||||
|
},
|
||||||
|
'complete': function (xhr, status) {
|
||||||
|
element.trigger('ajax:complete', [xhr, status]);
|
||||||
|
var html = xhr.responseText;
|
||||||
|
var content = xhr.getResponseHeader('web2py-component-content');
|
||||||
|
var t = $('#' + target);
|
||||||
|
if(content == 'prepend') t.prepend(html);
|
||||||
|
else if(content == 'append') t.append(html);
|
||||||
|
else if(content != 'hide') t.html(html);
|
||||||
|
web2py.trap_form(action, target);
|
||||||
|
web2py.trap_link(target);
|
||||||
|
web2py.ajax_init('#' + target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: function (action, target, timeout, times, el) {
|
||||||
|
//element is a new parameter, but should be put in front
|
||||||
|
$(function () {
|
||||||
|
var jelement = $("#" + target);
|
||||||
|
var element = jelement.get(0);
|
||||||
|
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||||
|
element.reload = function () {
|
||||||
|
// Continue if times is Infinity or
|
||||||
|
// the times limit is not reached
|
||||||
|
if(this.reload_check()) {
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
|
}
|
||||||
|
}; // reload
|
||||||
|
// Method to check timing limit
|
||||||
|
element.reload_check = function () {
|
||||||
|
if(jelement.hasClass('w2p_component_stop')) {
|
||||||
|
clearInterval(this.timing);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(this.reload_counter == Infinity) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(!isNaN(this.reload_counter)) {
|
||||||
|
this.reload_counter -= 1;
|
||||||
|
if(this.reload_counter < 0) {
|
||||||
|
if(!this.run_once) {
|
||||||
|
clearInterval(this.timing);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else{return true;}
|
} else {
|
||||||
} }
|
return true;
|
||||||
return false;}; // reload check
|
}
|
||||||
if (!isNaN(timeout)){
|
}
|
||||||
element.timeout = timeout;
|
}
|
||||||
element.reload_counter = times;
|
return false;
|
||||||
if (times > 1){
|
}; // reload check
|
||||||
// Multiple or infinite reload
|
if(!isNaN(timeout)) {
|
||||||
// Run first iteration
|
element.timeout = timeout;
|
||||||
web2py_ajax_page('get', action, null, target);
|
element.reload_counter = times;
|
||||||
element.run_once = false;
|
if(times > 1) {
|
||||||
element.timing = setInterval(statement, timeout);
|
// Multiple or infinite reload
|
||||||
element.reload_counter -= 1;
|
// Run first iteration
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
|
element.run_once = false;
|
||||||
|
element.timing = setInterval(statement, timeout);
|
||||||
|
element.reload_counter -= 1;
|
||||||
|
} else if(times == 1) {
|
||||||
|
// Run once with timeout
|
||||||
|
element.run_once = true;
|
||||||
|
element.setTimeout = setTimeout;
|
||||||
|
element.timing = setTimeout(statement, timeout);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// run once (no timeout specified)
|
||||||
|
element.reload_counter = Infinity;
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
}
|
}
|
||||||
else if (times == 1) {
|
});
|
||||||
// Run once with timeout
|
},
|
||||||
element.run_once = true;
|
calc_entropy: function (mystring) {
|
||||||
element.setTimeout = setTimeout;
|
//calculate a simple entropy for a given string
|
||||||
element.timing = setTimeout(statement, timeout);
|
var csets = new Array(
|
||||||
|
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||||
|
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||||
|
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||||
|
var score = 0,
|
||||||
|
other = {}, seen = {}, lastset = null,
|
||||||
|
mystringlist = mystring.split('');
|
||||||
|
for(var i = 0; i < mystringlist.length; i++) { // classify this character
|
||||||
|
var c = mystringlist[i],
|
||||||
|
inset = 5;
|
||||||
|
for(var j = 0; j < csets.length; j++)
|
||||||
|
if(csets[j].indexOf(c) != -1) {
|
||||||
|
inset = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//calculate effect of character on alphabet size
|
||||||
|
if(!(inset in seen)) {
|
||||||
|
seen[inset] = 1;
|
||||||
|
score += csets[inset].length;
|
||||||
|
} else if(!(c in other)) {
|
||||||
|
score += 1;
|
||||||
|
other[c] = 1;
|
||||||
}
|
}
|
||||||
} else {
|
if(inset != lastset) {
|
||||||
// run once (no timeout specified)
|
score += 1;
|
||||||
element.reload_counter = Infinity;
|
lastset = inset;
|
||||||
web2py_ajax_page('get', action, null, target);
|
}
|
||||||
} }); }
|
}
|
||||||
|
var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
|
||||||
|
return Math.round(entropy * 100) / 100
|
||||||
|
},
|
||||||
|
validate_entropy: function (myfield, req_entropy) {
|
||||||
|
//added
|
||||||
|
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy');
|
||||||
|
var validator = function () {
|
||||||
|
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
|
||||||
|
var r = 0,
|
||||||
|
g = 0,
|
||||||
|
b = 0,
|
||||||
|
rs = function (x) {
|
||||||
|
return Math.round(x * 15).toString(16)
|
||||||
|
};
|
||||||
|
if(v <= 0.5) {
|
||||||
|
r = 1.0;
|
||||||
|
g = 2.0 * v;
|
||||||
|
} else {
|
||||||
|
r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
|
||||||
|
g = 1.0;
|
||||||
|
}
|
||||||
|
var color = '#' + rs(r) + rs(g) + rs(b);
|
||||||
|
myfield.css('background-color', color);
|
||||||
|
entropy_callback = myfield.data('entropy_callback');
|
||||||
|
if(entropy_callback) entropy_callback(v);
|
||||||
|
}
|
||||||
|
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||||
|
},
|
||||||
|
web2py_websocket: function (url, onmessage, onopen, onclose) {
|
||||||
|
if("WebSocket" in window) {
|
||||||
|
var ws = new WebSocket(url);
|
||||||
|
ws.onopen = onopen ? onopen : (function () {});
|
||||||
|
ws.onmessage = onmessage;
|
||||||
|
ws.onclose = onclose ? onclose : (function () {});
|
||||||
|
return true; // supported
|
||||||
|
} else return false; // not supported
|
||||||
|
},
|
||||||
|
/* new from here */
|
||||||
|
// Form input elements bound by jquery-ujs
|
||||||
|
formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
|
||||||
|
// Form input elements disabled during form submission
|
||||||
|
disableSelector: 'input, button, textarea, select',
|
||||||
|
// Form input elements re-enabled after form submission
|
||||||
|
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
|
||||||
|
// Triggers an event on an element and returns false if the event result is false
|
||||||
|
fire: function (obj, name, data) {
|
||||||
|
var event = $.Event(name);
|
||||||
|
obj.trigger(event, data);
|
||||||
|
return event.result !== false;
|
||||||
|
},
|
||||||
|
// Helper function, needed to provide consistent behavior in IE
|
||||||
|
stopEverything: function (e) {
|
||||||
|
$(e.target).trigger('w2p:everythingStopped');
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
confirm: function (message) {
|
||||||
|
return confirm(message);
|
||||||
|
},
|
||||||
|
// replace element's html with the 'data-disable-with' after storing original html
|
||||||
|
// and prevent clicking on it
|
||||||
|
disableElement: function (el) {
|
||||||
|
el.addClass('disabled');
|
||||||
|
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||||
|
// store enabled state
|
||||||
|
el.data('w2p:enable-with', el[method]);
|
||||||
|
/* little addition by default*/
|
||||||
|
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
|
||||||
|
el.data('w2p_disable_with', 'Working...');
|
||||||
|
}
|
||||||
|
// set to disabled state
|
||||||
|
el[method](el.data('w2p_disable_with'));
|
||||||
|
|
||||||
function web2py_websocket(url,onmessage,onopen,onclose) {
|
el.bind('click.w2pDisable', function (e) { // prevent further clicking
|
||||||
if ("WebSocket" in window) {
|
return web2py.stopEverything(e);
|
||||||
var ws = new WebSocket(url);
|
});
|
||||||
ws.onopen = onopen?onopen:(function(){});
|
},
|
||||||
ws.onmessage = onmessage;
|
|
||||||
ws.onclose = onclose?onclose:(function(){});
|
|
||||||
return true; // supported
|
|
||||||
} else return false; // not supported
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// restore element to its original state which was disabled by 'disableElement' above
|
||||||
|
enableElement: function (el) {
|
||||||
|
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||||
|
if(el.data('w2p:enable-with') !== undefined) {
|
||||||
|
// set to old enabled state
|
||||||
|
el[method](el.data('w2p:enable-with'));
|
||||||
|
el.removeData('w2p:enable-with'); // clean up cache
|
||||||
|
}
|
||||||
|
el.removeClass('disabled');
|
||||||
|
el.unbind('click.w2pDisable'); // enable element
|
||||||
|
},
|
||||||
|
//convenience wrapper, internal use only
|
||||||
|
simple_component: function (action, target, element) {
|
||||||
|
web2py.component(action, target, 0, 1, element);
|
||||||
|
},
|
||||||
|
//helper for flash messages
|
||||||
|
flash: function(message, status) {
|
||||||
|
var flash = $('.flash');
|
||||||
|
web2py.hide_flash();
|
||||||
|
flash.html(message).addClass(status);
|
||||||
|
if(flash.html()) flash.append('<span id="closeflash"> × </span>').slideDown();
|
||||||
|
},
|
||||||
|
hide_flash: function() {
|
||||||
|
$('.flash').hide().html('');
|
||||||
|
},
|
||||||
|
a_handler: function (el, e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var method = el.data('w2p_method');
|
||||||
|
var action = el.attr('href');
|
||||||
|
var target = el.data('w2p_target');
|
||||||
|
var confirm_message = el.data('w2p_confirm');
|
||||||
|
|
||||||
function web2py_calc_entropy(mystring) {
|
var pre_call = el.data('w2p_pre_call');
|
||||||
//calculate a simple entropy for a given string
|
if(pre_call != undefined) {
|
||||||
var csets = new Array(
|
eval(pre_call);
|
||||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
}
|
||||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
if(confirm_message != undefined) {
|
||||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
if(confirm_message == 'default') confirm_message = w2p_ajax_confirm_message || 'Are you sure you want to delete this object?';
|
||||||
var score = 0, other = {}, seen = {}, lastset = null, mystringlist = mystring.split('');
|
if(!web2py.confirm(confirm_message)) {
|
||||||
for (var i=0;i<mystringlist.length;i++) { // classify this character
|
web2py.stopEverything(e);
|
||||||
var c = mystringlist[i], inset=5;
|
return;
|
||||||
for(var j = 0; j<csets.length; j++)
|
}
|
||||||
if (csets[j].indexOf(c) != -1) {inset = j; break;}
|
}
|
||||||
//calculate effect of character on alphabet size
|
if(target == undefined) {
|
||||||
if(!(inset in seen)) {seen[inset] = 1;score += csets[inset].length;}
|
if(method == 'GET') {
|
||||||
else if (!(c in other)) {score += 1;other[c] = 1;}
|
web2py.simple_component(action, el.attr('id'), el); //not working with original
|
||||||
if (inset != lastset) {score += 1;lastset = inset;}
|
} else if(method == 'POST') {
|
||||||
}
|
//should be web2py.ajax(action, [], ''); but it's too simple
|
||||||
var entropy = mystring.length*Math.log(score)/0.6931471805599453;
|
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
||||||
return Math.round(entropy*100)/100
|
}
|
||||||
}
|
} else {
|
||||||
|
if(method == 'GET') {
|
||||||
|
web2py.simple_component(action, target, el);
|
||||||
|
} else if(method == 'POST') {
|
||||||
|
//should be web2py.ajax(action, [], target); but it's too simple
|
||||||
|
web2py.ajax_page('post', action, [], target, el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*this should happen only on ajaxsuccess
|
||||||
|
* and should block subsequent clicks until ajaxcomplete
|
||||||
|
* NB: introduce the first incompatibility because normally
|
||||||
|
* the element would be removed in either case
|
||||||
|
/* removal code moved to the ajax:success event - START
|
||||||
|
if(toremove != undefined) {
|
||||||
|
toremove = el.closest(toremove);
|
||||||
|
if(!toremove.length) {
|
||||||
|
//this enables removal of whatever selector if a closest is not found
|
||||||
|
toremove = $(toremove);
|
||||||
|
}
|
||||||
|
toremove.remove();
|
||||||
|
}
|
||||||
|
/* removal code moved to the ajax:success event - END */
|
||||||
|
},
|
||||||
|
a_handlers: function () {
|
||||||
|
var el = $(document);
|
||||||
|
el.on('click', 'a[data-w2p_method]', function (e) {
|
||||||
|
web2py.a_handler($(this), e);
|
||||||
|
});
|
||||||
|
/* removal of element should happen only on success */
|
||||||
|
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function (e) {
|
||||||
|
var el = $(this);
|
||||||
|
var toremove = el.data('w2p_remove');
|
||||||
|
if(toremove != undefined) {
|
||||||
|
toremove = el.closest(toremove);
|
||||||
|
if(!toremove.length) {
|
||||||
|
//this enables removal of whatever selector if a closest is not found
|
||||||
|
toremove = $(toremove);
|
||||||
|
}
|
||||||
|
toremove.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||||
|
web2py.disableElement($(this));
|
||||||
|
});
|
||||||
|
/*re-enable click on completion*/
|
||||||
|
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||||
|
web2py.enableElement($(this));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/* Disables form elements:
|
||||||
|
- Caches element value in 'ujs:enable-with' data store
|
||||||
|
- Replaces element text with value of 'data-disable-with' attribute
|
||||||
|
- Sets disabled property to true
|
||||||
|
*/
|
||||||
|
disableFormElements: function(form) {
|
||||||
|
form.find(web2py.disableSelector).each(function() {
|
||||||
|
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||||
|
var disable_with = element.data('w2p_disable_with');
|
||||||
|
if (disable_with == undefined) {
|
||||||
|
element.data('w2p_disable_with', element[method]())
|
||||||
|
}
|
||||||
|
element.data('w2p:enable-with', element[method]());
|
||||||
|
element[method](element.data('w2p_disable_with'));
|
||||||
|
element.prop('disabled', true);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
function web2py_validate_entropy(myfield, req_entropy) {
|
/* Re-enables disabled form elements:
|
||||||
var validator = function () {
|
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
|
||||||
var v = (web2py_calc_entropy(myfield.val())||0)/req_entropy;
|
- Sets disabled property to false
|
||||||
var r=0,g=0,b=0,rs=function(x){return Math.round(x*15).toString(16)};
|
*/
|
||||||
if(v<=0.5) {r=1.0; g=2.0*v;}
|
enableFormElements: function(form) {
|
||||||
else {r=(1.0-2.0*(Math.max(v,0)-0.5)); g=1.0;}
|
form.find(web2py.enableSelector).each(function() {
|
||||||
var color = '#'+rs(r)+rs(g)+rs(b);
|
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||||
myfield.css('background-color',color);
|
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
|
||||||
entropy_callback = myfield.data('entropy_callback');
|
element.prop('disabled', false);
|
||||||
if(entropy_callback) entropy_callback(v);
|
});
|
||||||
}
|
},
|
||||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
form_handlers: function() {
|
||||||
}
|
var el = $(document);
|
||||||
|
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
|
||||||
function web2py_show_if(target) {
|
web2py.disableFormElements($(this));
|
||||||
var triggers = {};
|
});
|
||||||
var show_if = function () {
|
el.on('ajax:complete', 'form[data-w2p_target]', function (e) {
|
||||||
var t = jQuery(this);
|
web2py.enableFormElements($(this));
|
||||||
var id = t.attr('id');
|
});
|
||||||
t.attr('value', t.val());
|
|
||||||
for(var k = 0; k < triggers[id].length; k++) {
|
|
||||||
var dep = jQuery('#' + triggers[id][k], target);
|
|
||||||
var tr = jQuery('#' + triggers[id][k] + '__row', target);
|
|
||||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
|
||||||
else tr.hide();
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
jQuery('[data-show-trigger]', target).each(function () {
|
|
||||||
var name = jQuery(this).attr('data-show-trigger');
|
//end of functions
|
||||||
if(!triggers[name]) triggers[name] = [];
|
//main hook
|
||||||
triggers[name].push(jQuery(this).attr('id'));
|
$(function () {
|
||||||
});
|
var flash = $('.flash');
|
||||||
for(var name in triggers) {
|
flash.hide();
|
||||||
jQuery('#' + name, target).change(show_if).keyup(show_if);
|
if(flash.html()) web2py.flash(flash.html());
|
||||||
show_if.call(jQuery('#' + name, target));
|
web2py.ajax_init(document);
|
||||||
};
|
web2py.event_handlers();
|
||||||
}
|
web2py.a_handlers();
|
||||||
|
web2py.form_handlers();
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
/* compatibility code - start */
|
||||||
|
ajax = $.web2py.ajax;
|
||||||
|
web2py_component = $.web2py.component;
|
||||||
|
web2py_websocket = $.web2py.websocket;
|
||||||
|
web2py_ajax_page = $.web2py.ajax_page;
|
||||||
|
//needed for IS_STRONG(entropy)
|
||||||
|
web2py_validate_entropy = $.web2py.validate_entropy;
|
||||||
|
//needed for crud.search and SQLFORM.grid's search
|
||||||
|
web2py_ajax_fields = $.web2py.ajax_fields;
|
||||||
|
//used for LOAD(ajax=False)
|
||||||
|
web2py_trap_form = $.web2py.trap_form;
|
||||||
|
|
||||||
|
/*undocumented - rare*/
|
||||||
|
popup = $.web2py.popup;
|
||||||
|
collapse = $.web2py.collapse;
|
||||||
|
fade = $.web2py.fade;
|
||||||
|
|
||||||
|
/* internals - shouldn't be needed
|
||||||
|
|
||||||
|
web2py_ajax_init = $.web2py.ajax_init;
|
||||||
|
web2py_event_handlers = $.web2py.event_handlers;
|
||||||
|
|
||||||
|
web2py_trap_link = $.web2py.trap_link;
|
||||||
|
web2py_calc_entropy = $.web2py.calc_entropy;
|
||||||
|
*/
|
||||||
|
/* compatibility code - end*/
|
||||||
|
|||||||
@@ -1,242 +1,617 @@
|
|||||||
function popup(url) {
|
(function ($, undefined) {
|
||||||
newwindow=window.open(url,'name','height=400,width=600');
|
/*
|
||||||
if (window.focus) newwindow.focus();
|
* Unobtrusive scripting adapter for jQuery, largely taken from
|
||||||
return false;
|
* the wonderful https://github.com/rails/jquery-ujs
|
||||||
}
|
*
|
||||||
function collapse(id) { jQuery('#'+id).slideToggle(); }
|
*
|
||||||
function fade(id,value) { if(value>0) jQuery('#'+id).hide().fadeIn('slow'); else jQuery('#'+id).show().fadeOut('slow'); }
|
* Released under the MIT license
|
||||||
function ajax(u,s,t) {
|
*
|
||||||
query = '';
|
*/
|
||||||
if (typeof s == "string") {
|
|
||||||
d = jQuery(s).serialize();
|
String.prototype.reverse = function () {
|
||||||
if(d){ query = d; }
|
return this.split('').reverse().join('');
|
||||||
} else {
|
};
|
||||||
|
var web2py;
|
||||||
|
|
||||||
|
$.web2py = web2py = {
|
||||||
|
|
||||||
|
popup: function (url) {
|
||||||
|
newwindow = window.open(url, 'name', 'height=400,width=600');
|
||||||
|
if(window.focus) newwindow.focus();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
collapse: function () {
|
||||||
|
$('#' + id).slideToggle();
|
||||||
|
},
|
||||||
|
fade: function (id, value) {
|
||||||
|
if(value > 0) $('#' + id).hide().fadeIn('slow');
|
||||||
|
else $('#' + id).show().fadeOut('slow');
|
||||||
|
},
|
||||||
|
ajax: function (u, s, t) {
|
||||||
|
query = '';
|
||||||
|
if(typeof s == "string") {
|
||||||
|
d = $(s).serialize();
|
||||||
|
if(d) {
|
||||||
|
query = d;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
pcs = [];
|
pcs = [];
|
||||||
if (s != null && s != undefined) for(i=0; i<s.length; i++) {
|
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
|
||||||
q = jQuery("[name="+s[i]+"]").serialize();
|
q = $("[name=" + s[i] + "]").serialize();
|
||||||
if(q){pcs.push(q);}
|
if(q) {
|
||||||
|
pcs.push(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pcs.length > 0) {
|
||||||
|
query = pcs.join("&");
|
||||||
}
|
}
|
||||||
if (pcs.length>0){query = pcs.join("&");}
|
|
||||||
}
|
|
||||||
jQuery.ajax({type: "POST", url: u, data: query, success: function(msg) { if(t) { if(t==':eval') eval(msg); else if(typeof t=='string') jQuery("#"+t).html(msg); else t(msg); } } });
|
|
||||||
}
|
|
||||||
|
|
||||||
String.prototype.reverse = function () { return this.split('').reverse().join('');};
|
|
||||||
function web2py_ajax_fields(target) {
|
|
||||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
|
||||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
|
||||||
jQuery("input.date",target).each(function() {Calendar.setup({inputField:this, ifFormat:date_format, showsTime:false });});
|
|
||||||
jQuery("input.datetime",target).each(function() {Calendar.setup({inputField:this, ifFormat:datetime_format, showsTime: true, timeFormat: "24" });});
|
|
||||||
jQuery("input.time",target).each(function(){jQuery(this).timeEntry();});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function web2py_ajax_init(target) {
|
|
||||||
jQuery('.hidden', target).hide();
|
|
||||||
jQuery('.error', target).hide().slideDown('slow');
|
|
||||||
web2py_ajax_fields(target);
|
|
||||||
web2py_show_if(target);
|
|
||||||
};
|
|
||||||
|
|
||||||
function web2py_event_handlers() {
|
|
||||||
var doc = jQuery(document)
|
|
||||||
doc.on('click', '.flash', function(e){var t=jQuery(this); if(t.css('top')=='0px') t.slideUp('slow'); else t.fadeOut(); e.preventDefault();});
|
|
||||||
doc.on('keyup', 'input.integer', function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});
|
|
||||||
doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();});
|
|
||||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
|
||||||
doc.on('click', "input[type='checkbox'].delete", function(){if(this.checked) if(!confirm(confirm_message)) this.checked=false;});
|
|
||||||
|
|
||||||
doc.ajaxSuccess(function(e, xhr) {
|
|
||||||
var redirect=xhr.getResponseHeader('web2py-redirect-location');
|
|
||||||
var command=xhr.getResponseHeader('web2py-component-command');
|
|
||||||
var flash=xhr.getResponseHeader('web2py-component-flash');
|
|
||||||
if (redirect !== null) {
|
|
||||||
window.location = redirect;
|
|
||||||
};
|
|
||||||
if(command !== null){
|
|
||||||
eval(decodeURIComponent(command));
|
|
||||||
}
|
|
||||||
if(flash) {
|
|
||||||
jQuery('.flash')
|
|
||||||
.html(decodeURIComponent(flash))
|
|
||||||
.append('<span id="closeflash">×</span>')
|
|
||||||
.slideDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
doc.ajaxError(function(e, xhr, settings, exception) {
|
|
||||||
doc.off('click', '.flash')
|
|
||||||
switch(xhr.status){
|
|
||||||
case 500:
|
|
||||||
$('.flash').html(ajax_error_500).slideDown();
|
|
||||||
}
|
}
|
||||||
});
|
$.ajax({
|
||||||
};
|
type: "POST",
|
||||||
|
url: u,
|
||||||
jQuery(function() {
|
data: query,
|
||||||
var flash = jQuery('.flash');
|
success: function (msg) {
|
||||||
flash.hide();
|
if(t) {
|
||||||
if(flash.html()) flash.append('<span id="closeflash">×</span>').slideDown();
|
if(t == ':eval') eval(msg);
|
||||||
web2py_ajax_init(document);
|
else if(typeof t == 'string') $("#" + t).html(msg);
|
||||||
web2py_event_handlers();
|
else t(msg);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
function web2py_trap_form(action,target) {
|
|
||||||
jQuery('#'+target+' form').each(function(i){
|
|
||||||
var form=jQuery(this);
|
|
||||||
if(!form.hasClass('no_trap'))
|
|
||||||
form.submit(function(e){
|
|
||||||
jQuery('.flash').hide().html('');
|
|
||||||
web2py_ajax_page('post',action,form.serialize(),target);
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
}
|
ajax_fields: function (target) {
|
||||||
|
/*this attaches something to a newly loaded fragment/page
|
||||||
function web2py_trap_link(target) {
|
* Ideally all events should be bound to the document, so we can avoid calling
|
||||||
jQuery('#'+target+' a.w2p_trap').each(function(i){
|
* this over and over... all will be bound to the document
|
||||||
var link=jQuery(this);
|
*/
|
||||||
link.click(function(e) {
|
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||||
jQuery('.flash').hide().html('');
|
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||||
web2py_ajax_page('get',link.attr('href'),[],target);
|
$("input.date", target).each(function () {
|
||||||
e.preventDefault();
|
Calendar.setup({
|
||||||
});
|
inputField: this,
|
||||||
|
ifFormat: date_format,
|
||||||
|
showsTime: false
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
$("input.datetime", target).each(function () {
|
||||||
|
Calendar.setup({
|
||||||
|
inputField: this,
|
||||||
|
ifFormat: datetime_format,
|
||||||
|
showsTime: true,
|
||||||
|
timeFormat: "24"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$("input.time", target).each(function () {
|
||||||
|
$(this).timeEntry();
|
||||||
|
});
|
||||||
|
/*adds btn class to buttons*/
|
||||||
|
$('button', target).addClass('btn');
|
||||||
|
$('form input[type="submit"], form input[type="button"]', target).addClass('btn');
|
||||||
|
/*no more inline javascript for PasswordWidget*/
|
||||||
|
$('input[type=password][data-w2p_entropy]', target).each(function () {
|
||||||
|
web2py.validate_entropy($(this));
|
||||||
|
});
|
||||||
|
/*no more inline javascript for ListWidget*/
|
||||||
|
$('ul.w2p_list', target).each(function () {
|
||||||
|
function pe(ul, e) {
|
||||||
|
var new_line = ml(ul);
|
||||||
|
rel(ul);
|
||||||
|
if($(e.target).parent().is(':visible')) {
|
||||||
|
//make sure we didn't delete the element before we insert after
|
||||||
|
new_line.insertAfter($(e.target).parent());
|
||||||
|
} else {
|
||||||
|
//the line we clicked on was deleted, just add to end of list
|
||||||
|
new_line.appendTo(ul);
|
||||||
|
}
|
||||||
|
new_line.find(":text").focus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function web2py_ajax_page(method, action, data, target) {
|
function rl(ul, e) {
|
||||||
jQuery.ajax({'type':method, 'url':action, 'data':data,
|
if($(ul).children().length > 1) {
|
||||||
'beforeSend':function(xhr) {
|
//only remove if we have more than 1 item so the list is never empty
|
||||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
$(e.target).parent().remove();
|
||||||
xhr.setRequestHeader('web2py-component-element', target);},
|
}
|
||||||
'complete':function(xhr,text){
|
}
|
||||||
var html=xhr.responseText;
|
|
||||||
var content=xhr.getResponseHeader('web2py-component-content');
|
|
||||||
var t = jQuery('#'+target);
|
|
||||||
if(content=='prepend') t.prepend(html);
|
|
||||||
else if(content=='append') t.append(html);
|
|
||||||
else if(content!='hide') t.html(html);
|
|
||||||
web2py_trap_form(action,target);
|
|
||||||
web2py_trap_link(target);
|
|
||||||
web2py_ajax_init('#'+target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function web2py_component(action, target, timeout, times){
|
function ml(ul) {
|
||||||
jQuery(function(){
|
var line = $(ul).find("li:first").clone(true);
|
||||||
var jelement = jQuery("#" + target);
|
line.find(':text').val('');
|
||||||
var element = jelement.get(0);
|
return line;
|
||||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
}
|
||||||
jelement.reload = function (){
|
|
||||||
// Continue if times is Infinity or
|
function rel(ul) {
|
||||||
// the times limit is not reached
|
$(ul).find("li").each(function () {
|
||||||
if (element.reload_check()){
|
var trimmed = $.trim($(this.firstChild).val());
|
||||||
web2py_ajax_page('get', action, null, target);} }; // reload
|
if(trimmed == '') $(this).remove();
|
||||||
// Method to check timing limit
|
else $(this.firstChild).val(trimmed);
|
||||||
element.reload_check = function (){
|
});
|
||||||
if (jelement.hasClass('w2p_component_stop')) {clearInterval(this.timing);return false;}
|
}
|
||||||
if (this.reload_counter == Infinity){return true;}
|
var ul = this;
|
||||||
else {
|
$(ul).find(":text").after('<a href="#">+</a> <a href="#">-</a>').keypress(function (e) {
|
||||||
if (!isNaN(this.reload_counter)){
|
return(e.which == 13) ? pe(ul, e) : true;
|
||||||
this.reload_counter -= 1;
|
}).next().click(function (e) {
|
||||||
if (this.reload_counter < 0){
|
pe(ul, e);
|
||||||
if (!this.run_once){
|
e.preventDefault();
|
||||||
clearInterval(this.timing);
|
}).next().click(function (e) {
|
||||||
return false;
|
rl(ul, e);
|
||||||
}
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ajax_init: function (target) {
|
||||||
|
$('.hidden', target).hide();
|
||||||
|
web2py.manage_errors(target);
|
||||||
|
web2py.ajax_fields(target);
|
||||||
|
},
|
||||||
|
//manage errors in forms
|
||||||
|
manage_errors: function(target) {
|
||||||
|
$('.error', target).hide().slideDown('slow');
|
||||||
|
//$('.error', target).hide().fadeIn('slow');
|
||||||
|
},
|
||||||
|
event_handlers: function () {
|
||||||
|
/* This is called once for page
|
||||||
|
* Ideally it should bound all the things that are needed
|
||||||
|
*/
|
||||||
|
var doc = $(document);
|
||||||
|
doc.on('click', '.flash', function (e) {
|
||||||
|
console.log('das');
|
||||||
|
var t = $(this);
|
||||||
|
if(t.css('top') == '0px') t.slideUp('slow');
|
||||||
|
else t.fadeOut();
|
||||||
|
//if I want to display a clickable something
|
||||||
|
//inside flash, I should not be prevented to follow it
|
||||||
|
//e.preventDefault();
|
||||||
|
});
|
||||||
|
doc.on('keyup', 'input.integer', function () {
|
||||||
|
this.value = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
|
||||||
|
});
|
||||||
|
doc.on('keyup', 'input.double, input.decimal', function () {
|
||||||
|
this.value = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
|
||||||
|
});
|
||||||
|
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||||
|
doc.on('click', "input[type='checkbox'].delete", function () {
|
||||||
|
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.ajaxSuccess(function (e, xhr) {
|
||||||
|
var redirect = xhr.getResponseHeader('web2py-redirect-location');
|
||||||
|
var command = xhr.getResponseHeader('web2py-component-command');
|
||||||
|
var flash = xhr.getResponseHeader('web2py-component-flash');
|
||||||
|
if(redirect !== null) {
|
||||||
|
window.location = redirect;
|
||||||
|
};
|
||||||
|
if(command !== null) {
|
||||||
|
eval(decodeURIComponent(command));
|
||||||
|
}
|
||||||
|
if(flash) {
|
||||||
|
web2py.flash(decodeURIComponent(flash))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.ajaxError(function (e, xhr, settings, exception) {
|
||||||
|
//personally I don't like it.
|
||||||
|
//if there's an error it it flashed and can be removed
|
||||||
|
//as any other message
|
||||||
|
//doc.off('click', '.flash')
|
||||||
|
switch(xhr.status) {
|
||||||
|
case 500:
|
||||||
|
web2py.flash(ajax_error_500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
trap_form: function (action, target) {
|
||||||
|
$('#' + target + ' form').each(function (i) {
|
||||||
|
var form = $(this);
|
||||||
|
form.attr('data-w2p_target', target);
|
||||||
|
if(!form.hasClass('no_trap')) {
|
||||||
|
//should be there by default ?
|
||||||
|
form.find('input[type=submit]').attr('data-w2p_disable_with', 'Working...');
|
||||||
|
form.submit(function (e) {
|
||||||
|
web2py.hide_flash();
|
||||||
|
web2py.ajax_page('post', action, form.serialize(), target, form);
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
trap_link: function (target) {
|
||||||
|
$('#' + target + ' a.w2p_trap').each(function (i) {
|
||||||
|
var link = $(this);
|
||||||
|
link.click(function (e) {
|
||||||
|
web2py.hide_flash();
|
||||||
|
web2py.ajax_page('get', link.attr('href'), [], target);
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ajax_page: function (method, action, data, target, element) {
|
||||||
|
//element is a new parameter, but should be put be put in front
|
||||||
|
if(element == undefined) element = $(document);
|
||||||
|
if(web2py.fire(element, 'ajax:before')) { //test a usecase, should stop here if returns false
|
||||||
|
$.ajax({
|
||||||
|
'type': method,
|
||||||
|
'url': action,
|
||||||
|
'data': data,
|
||||||
|
'beforeSend': function (xhr, settings) {
|
||||||
|
//added
|
||||||
|
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||||
|
xhr.setRequestHeader('web2py-component-element', target);
|
||||||
|
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings]); //test a usecase, should stop here if returns false
|
||||||
|
},
|
||||||
|
//added
|
||||||
|
'success': function (data, status, xhr) {
|
||||||
|
//bummer for form submissions....the element is not there after complete
|
||||||
|
//because it gets replaced by the new response....
|
||||||
|
element.trigger('ajax:success', [data, status, xhr]);
|
||||||
|
},
|
||||||
|
//added
|
||||||
|
'error': function (xhr, status, error) {
|
||||||
|
//bummer for form submissions....in addition to the element being not there after
|
||||||
|
//complete because it gets replaced by the new response, standard form
|
||||||
|
//handling just returns the same status code for good and bad
|
||||||
|
//form submissions (i.e. that triggered a validator error)
|
||||||
|
element.trigger('ajax:error', [xhr, status, error]);
|
||||||
|
},
|
||||||
|
'complete': function (xhr, status) {
|
||||||
|
element.trigger('ajax:complete', [xhr, status]);
|
||||||
|
var html = xhr.responseText;
|
||||||
|
var content = xhr.getResponseHeader('web2py-component-content');
|
||||||
|
var t = $('#' + target);
|
||||||
|
if(content == 'prepend') t.prepend(html);
|
||||||
|
else if(content == 'append') t.append(html);
|
||||||
|
else if(content != 'hide') t.html(html);
|
||||||
|
web2py.trap_form(action, target);
|
||||||
|
web2py.trap_link(target);
|
||||||
|
web2py.ajax_init('#' + target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: function (action, target, timeout, times, el) {
|
||||||
|
//element is a new parameter, but should be put in front
|
||||||
|
$(function () {
|
||||||
|
var jelement = $("#" + target);
|
||||||
|
var element = jelement.get(0);
|
||||||
|
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||||
|
element.reload = function () {
|
||||||
|
// Continue if times is Infinity or
|
||||||
|
// the times limit is not reached
|
||||||
|
if(this.reload_check()) {
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
|
}
|
||||||
|
}; // reload
|
||||||
|
// Method to check timing limit
|
||||||
|
element.reload_check = function () {
|
||||||
|
if(jelement.hasClass('w2p_component_stop')) {
|
||||||
|
clearInterval(this.timing);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(this.reload_counter == Infinity) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(!isNaN(this.reload_counter)) {
|
||||||
|
this.reload_counter -= 1;
|
||||||
|
if(this.reload_counter < 0) {
|
||||||
|
if(!this.run_once) {
|
||||||
|
clearInterval(this.timing);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else{return true;}
|
} else {
|
||||||
} }
|
return true;
|
||||||
return false;}; // reload check
|
}
|
||||||
if (!isNaN(timeout)){
|
}
|
||||||
element.timeout = timeout;
|
}
|
||||||
element.reload_counter = times;
|
return false;
|
||||||
if (times > 1){
|
}; // reload check
|
||||||
// Multiple or infinite reload
|
if(!isNaN(timeout)) {
|
||||||
// Run first iteration
|
element.timeout = timeout;
|
||||||
web2py_ajax_page('get', action, null, target);
|
element.reload_counter = times;
|
||||||
element.run_once = false;
|
if(times > 1) {
|
||||||
element.timing = setInterval(statement, timeout);
|
// Multiple or infinite reload
|
||||||
element.reload_counter -= 1;
|
// Run first iteration
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
|
element.run_once = false;
|
||||||
|
element.timing = setInterval(statement, timeout);
|
||||||
|
element.reload_counter -= 1;
|
||||||
|
} else if(times == 1) {
|
||||||
|
// Run once with timeout
|
||||||
|
element.run_once = true;
|
||||||
|
element.setTimeout = setTimeout;
|
||||||
|
element.timing = setTimeout(statement, timeout);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// run once (no timeout specified)
|
||||||
|
element.reload_counter = Infinity;
|
||||||
|
web2py.ajax_page('get', action, null, target, el);
|
||||||
}
|
}
|
||||||
else if (times == 1) {
|
});
|
||||||
// Run once with timeout
|
},
|
||||||
element.run_once = true;
|
calc_entropy: function (mystring) {
|
||||||
element.setTimeout = setTimeout;
|
//calculate a simple entropy for a given string
|
||||||
element.timing = setTimeout(statement, timeout);
|
var csets = new Array(
|
||||||
|
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||||
|
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||||
|
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||||
|
var score = 0,
|
||||||
|
other = {}, seen = {}, lastset = null,
|
||||||
|
mystringlist = mystring.split('');
|
||||||
|
for(var i = 0; i < mystringlist.length; i++) { // classify this character
|
||||||
|
var c = mystringlist[i],
|
||||||
|
inset = 5;
|
||||||
|
for(var j = 0; j < csets.length; j++)
|
||||||
|
if(csets[j].indexOf(c) != -1) {
|
||||||
|
inset = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//calculate effect of character on alphabet size
|
||||||
|
if(!(inset in seen)) {
|
||||||
|
seen[inset] = 1;
|
||||||
|
score += csets[inset].length;
|
||||||
|
} else if(!(c in other)) {
|
||||||
|
score += 1;
|
||||||
|
other[c] = 1;
|
||||||
}
|
}
|
||||||
} else {
|
if(inset != lastset) {
|
||||||
// run once (no timeout specified)
|
score += 1;
|
||||||
element.reload_counter = Infinity;
|
lastset = inset;
|
||||||
web2py_ajax_page('get', action, null, target);
|
}
|
||||||
} }); }
|
}
|
||||||
|
var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
|
||||||
|
return Math.round(entropy * 100) / 100
|
||||||
|
},
|
||||||
|
validate_entropy: function (myfield, req_entropy) {
|
||||||
|
//added
|
||||||
|
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy');
|
||||||
|
var validator = function () {
|
||||||
|
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
|
||||||
|
var r = 0,
|
||||||
|
g = 0,
|
||||||
|
b = 0,
|
||||||
|
rs = function (x) {
|
||||||
|
return Math.round(x * 15).toString(16)
|
||||||
|
};
|
||||||
|
if(v <= 0.5) {
|
||||||
|
r = 1.0;
|
||||||
|
g = 2.0 * v;
|
||||||
|
} else {
|
||||||
|
r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
|
||||||
|
g = 1.0;
|
||||||
|
}
|
||||||
|
var color = '#' + rs(r) + rs(g) + rs(b);
|
||||||
|
myfield.css('background-color', color);
|
||||||
|
entropy_callback = myfield.data('entropy_callback');
|
||||||
|
if(entropy_callback) entropy_callback(v);
|
||||||
|
}
|
||||||
|
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||||
|
},
|
||||||
|
web2py_websocket: function (url, onmessage, onopen, onclose) {
|
||||||
|
if("WebSocket" in window) {
|
||||||
|
var ws = new WebSocket(url);
|
||||||
|
ws.onopen = onopen ? onopen : (function () {});
|
||||||
|
ws.onmessage = onmessage;
|
||||||
|
ws.onclose = onclose ? onclose : (function () {});
|
||||||
|
return true; // supported
|
||||||
|
} else return false; // not supported
|
||||||
|
},
|
||||||
|
/* new from here */
|
||||||
|
// Form input elements bound by jquery-ujs
|
||||||
|
formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
|
||||||
|
// Form input elements disabled during form submission
|
||||||
|
disableSelector: 'input, button, textarea, select',
|
||||||
|
// Form input elements re-enabled after form submission
|
||||||
|
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
|
||||||
|
// Triggers an event on an element and returns false if the event result is false
|
||||||
|
fire: function (obj, name, data) {
|
||||||
|
var event = $.Event(name);
|
||||||
|
obj.trigger(event, data);
|
||||||
|
return event.result !== false;
|
||||||
|
},
|
||||||
|
// Helper function, needed to provide consistent behavior in IE
|
||||||
|
stopEverything: function (e) {
|
||||||
|
$(e.target).trigger('w2p:everythingStopped');
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
confirm: function (message) {
|
||||||
|
return confirm(message);
|
||||||
|
},
|
||||||
|
// replace element's html with the 'data-disable-with' after storing original html
|
||||||
|
// and prevent clicking on it
|
||||||
|
disableElement: function (el) {
|
||||||
|
el.addClass('disabled');
|
||||||
|
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||||
|
// store enabled state
|
||||||
|
el.data('w2p:enable-with', el[method]);
|
||||||
|
/* little addition by default*/
|
||||||
|
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
|
||||||
|
el.data('w2p_disable_with', 'Working...');
|
||||||
|
}
|
||||||
|
// set to disabled state
|
||||||
|
el[method](el.data('w2p_disable_with'));
|
||||||
|
|
||||||
function web2py_websocket(url,onmessage,onopen,onclose) {
|
el.bind('click.w2pDisable', function (e) { // prevent further clicking
|
||||||
if ("WebSocket" in window) {
|
return web2py.stopEverything(e);
|
||||||
var ws = new WebSocket(url);
|
});
|
||||||
ws.onopen = onopen?onopen:(function(){});
|
},
|
||||||
ws.onmessage = onmessage;
|
|
||||||
ws.onclose = onclose?onclose:(function(){});
|
|
||||||
return true; // supported
|
|
||||||
} else return false; // not supported
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// restore element to its original state which was disabled by 'disableElement' above
|
||||||
|
enableElement: function (el) {
|
||||||
|
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||||
|
if(el.data('w2p:enable-with') !== undefined) {
|
||||||
|
// set to old enabled state
|
||||||
|
el[method](el.data('w2p:enable-with'));
|
||||||
|
el.removeData('w2p:enable-with'); // clean up cache
|
||||||
|
}
|
||||||
|
el.removeClass('disabled');
|
||||||
|
el.unbind('click.w2pDisable'); // enable element
|
||||||
|
},
|
||||||
|
//convenience wrapper, internal use only
|
||||||
|
simple_component: function (action, target, element) {
|
||||||
|
web2py.component(action, target, 0, 1, element);
|
||||||
|
},
|
||||||
|
//helper for flash messages
|
||||||
|
flash: function(message, status) {
|
||||||
|
var flash = $('.flash');
|
||||||
|
web2py.hide_flash();
|
||||||
|
flash.html(message).addClass(status);
|
||||||
|
if(flash.html()) flash.append('<span id="closeflash"> × </span>').slideDown();
|
||||||
|
},
|
||||||
|
hide_flash: function() {
|
||||||
|
$('.flash').hide().html('');
|
||||||
|
},
|
||||||
|
a_handler: function (el, e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var method = el.data('w2p_method');
|
||||||
|
var action = el.attr('href');
|
||||||
|
var target = el.data('w2p_target');
|
||||||
|
var confirm_message = el.data('w2p_confirm');
|
||||||
|
|
||||||
function web2py_calc_entropy(mystring) {
|
var pre_call = el.data('w2p_pre_call');
|
||||||
//calculate a simple entropy for a given string
|
if(pre_call != undefined) {
|
||||||
var csets = new Array(
|
eval(pre_call);
|
||||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
}
|
||||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
if(confirm_message != undefined) {
|
||||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
if(confirm_message == 'default') confirm_message = w2p_ajax_confirm_message || 'Are you sure you want to delete this object?';
|
||||||
var score = 0, other = {}, seen = {}, lastset = null, mystringlist = mystring.split('');
|
if(!web2py.confirm(confirm_message)) {
|
||||||
for (var i=0;i<mystringlist.length;i++) { // classify this character
|
web2py.stopEverything(e);
|
||||||
var c = mystringlist[i], inset=5;
|
return;
|
||||||
for(var j = 0; j<csets.length; j++)
|
}
|
||||||
if (csets[j].indexOf(c) != -1) {inset = j; break;}
|
}
|
||||||
//calculate effect of character on alphabet size
|
if(target == undefined) {
|
||||||
if(!(inset in seen)) {seen[inset] = 1;score += csets[inset].length;}
|
if(method == 'GET') {
|
||||||
else if (!(c in other)) {score += 1;other[c] = 1;}
|
web2py.simple_component(action, el.attr('id'), el); //not working with original
|
||||||
if (inset != lastset) {score += 1;lastset = inset;}
|
} else if(method == 'POST') {
|
||||||
}
|
//should be web2py.ajax(action, [], ''); but it's too simple
|
||||||
var entropy = mystring.length*Math.log(score)/0.6931471805599453;
|
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
||||||
return Math.round(entropy*100)/100
|
}
|
||||||
}
|
} else {
|
||||||
|
if(method == 'GET') {
|
||||||
|
web2py.simple_component(action, target, el);
|
||||||
|
} else if(method == 'POST') {
|
||||||
|
//should be web2py.ajax(action, [], target); but it's too simple
|
||||||
|
web2py.ajax_page('post', action, [], target, el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*this should happen only on ajaxsuccess
|
||||||
|
* and should block subsequent clicks until ajaxcomplete
|
||||||
|
* NB: introduce the first incompatibility because normally
|
||||||
|
* the element would be removed in either case
|
||||||
|
/* removal code moved to the ajax:success event - START
|
||||||
|
if(toremove != undefined) {
|
||||||
|
toremove = el.closest(toremove);
|
||||||
|
if(!toremove.length) {
|
||||||
|
//this enables removal of whatever selector if a closest is not found
|
||||||
|
toremove = $(toremove);
|
||||||
|
}
|
||||||
|
toremove.remove();
|
||||||
|
}
|
||||||
|
/* removal code moved to the ajax:success event - END */
|
||||||
|
},
|
||||||
|
a_handlers: function () {
|
||||||
|
var el = $(document);
|
||||||
|
el.on('click', 'a[data-w2p_method]', function (e) {
|
||||||
|
web2py.a_handler($(this), e);
|
||||||
|
});
|
||||||
|
/* removal of element should happen only on success */
|
||||||
|
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function (e) {
|
||||||
|
var el = $(this);
|
||||||
|
var toremove = el.data('w2p_remove');
|
||||||
|
if(toremove != undefined) {
|
||||||
|
toremove = el.closest(toremove);
|
||||||
|
if(!toremove.length) {
|
||||||
|
//this enables removal of whatever selector if a closest is not found
|
||||||
|
toremove = $(toremove);
|
||||||
|
}
|
||||||
|
toremove.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||||
|
web2py.disableElement($(this));
|
||||||
|
});
|
||||||
|
/*re-enable click on completion*/
|
||||||
|
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||||
|
web2py.enableElement($(this));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/* Disables form elements:
|
||||||
|
- Caches element value in 'ujs:enable-with' data store
|
||||||
|
- Replaces element text with value of 'data-disable-with' attribute
|
||||||
|
- Sets disabled property to true
|
||||||
|
*/
|
||||||
|
disableFormElements: function(form) {
|
||||||
|
form.find(web2py.disableSelector).each(function() {
|
||||||
|
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||||
|
var disable_with = element.data('w2p_disable_with');
|
||||||
|
if (disable_with == undefined) {
|
||||||
|
element.data('w2p_disable_with', element[method]())
|
||||||
|
}
|
||||||
|
element.data('w2p:enable-with', element[method]());
|
||||||
|
element[method](element.data('w2p_disable_with'));
|
||||||
|
element.prop('disabled', true);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
function web2py_validate_entropy(myfield, req_entropy) {
|
/* Re-enables disabled form elements:
|
||||||
var validator = function () {
|
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
|
||||||
var v = (web2py_calc_entropy(myfield.val())||0)/req_entropy;
|
- Sets disabled property to false
|
||||||
var r=0,g=0,b=0,rs=function(x){return Math.round(x*15).toString(16)};
|
*/
|
||||||
if(v<=0.5) {r=1.0; g=2.0*v;}
|
enableFormElements: function(form) {
|
||||||
else {r=(1.0-2.0*(Math.max(v,0)-0.5)); g=1.0;}
|
form.find(web2py.enableSelector).each(function() {
|
||||||
var color = '#'+rs(r)+rs(g)+rs(b);
|
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||||
myfield.css('background-color',color);
|
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
|
||||||
entropy_callback = myfield.data('entropy_callback');
|
element.prop('disabled', false);
|
||||||
if(entropy_callback) entropy_callback(v);
|
});
|
||||||
}
|
},
|
||||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
form_handlers: function() {
|
||||||
}
|
var el = $(document);
|
||||||
|
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
|
||||||
function web2py_show_if(target) {
|
web2py.disableFormElements($(this));
|
||||||
var triggers = {};
|
});
|
||||||
var show_if = function () {
|
el.on('ajax:complete', 'form[data-w2p_target]', function (e) {
|
||||||
var t = jQuery(this);
|
web2py.enableFormElements($(this));
|
||||||
var id = t.attr('id');
|
});
|
||||||
t.attr('value', t.val());
|
|
||||||
for(var k = 0; k < triggers[id].length; k++) {
|
|
||||||
var dep = jQuery('#' + triggers[id][k], target);
|
|
||||||
var tr = jQuery('#' + triggers[id][k] + '__row', target);
|
|
||||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
|
||||||
else tr.hide();
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
jQuery('[data-show-trigger]', target).each(function () {
|
|
||||||
var name = jQuery(this).attr('data-show-trigger');
|
//end of functions
|
||||||
if(!triggers[name]) triggers[name] = [];
|
//main hook
|
||||||
triggers[name].push(jQuery(this).attr('id'));
|
$(function () {
|
||||||
});
|
var flash = $('.flash');
|
||||||
for(var name in triggers) {
|
flash.hide();
|
||||||
jQuery('#' + name, target).change(show_if).keyup(show_if);
|
if(flash.html()) web2py.flash(flash.html());
|
||||||
show_if.call(jQuery('#' + name, target));
|
web2py.ajax_init(document);
|
||||||
};
|
web2py.event_handlers();
|
||||||
}
|
web2py.a_handlers();
|
||||||
|
web2py.form_handlers();
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
/* compatibility code - start */
|
||||||
|
ajax = $.web2py.ajax;
|
||||||
|
web2py_component = $.web2py.component;
|
||||||
|
web2py_websocket = $.web2py.websocket;
|
||||||
|
web2py_ajax_page = $.web2py.ajax_page;
|
||||||
|
//needed for IS_STRONG(entropy)
|
||||||
|
web2py_validate_entropy = $.web2py.validate_entropy;
|
||||||
|
//needed for crud.search and SQLFORM.grid's search
|
||||||
|
web2py_ajax_fields = $.web2py.ajax_fields;
|
||||||
|
//used for LOAD(ajax=False)
|
||||||
|
web2py_trap_form = $.web2py.trap_form;
|
||||||
|
|
||||||
|
/*undocumented - rare*/
|
||||||
|
popup = $.web2py.popup;
|
||||||
|
collapse = $.web2py.collapse;
|
||||||
|
fade = $.web2py.fade;
|
||||||
|
|
||||||
|
/* internals - shouldn't be needed
|
||||||
|
|
||||||
|
web2py_ajax_init = $.web2py.ajax_init;
|
||||||
|
web2py_event_handlers = $.web2py.event_handlers;
|
||||||
|
|
||||||
|
web2py_trap_link = $.web2py.trap_link;
|
||||||
|
web2py_calc_entropy = $.web2py.calc_entropy;
|
||||||
|
*/
|
||||||
|
/* compatibility code - end*/
|
||||||
|
|||||||
+19
-19
@@ -1479,30 +1479,30 @@ class A(DIV):
|
|||||||
def xml(self):
|
def xml(self):
|
||||||
if not self.components and self['_href']:
|
if not self.components and self['_href']:
|
||||||
self.append(self['_href'])
|
self.append(self['_href'])
|
||||||
|
if not self['_disable_with']:
|
||||||
|
self['_data-w2p_disable_with'] = 'default'
|
||||||
if self['delete']:
|
if self['delete']:
|
||||||
d = "jQuery(this).closest('%s').remove();" % self['delete']
|
self['_data-w2p_remove'] = self['delete']
|
||||||
else:
|
if self['target']:
|
||||||
d = ''
|
self['_data-w2p_target'] = self['target']
|
||||||
if self['component']:
|
if self['component']:
|
||||||
self['_onclick'] = "web2py_component('%s','%s');%sreturn false;" % \
|
self['_data-w2p_method'] = 'GET'
|
||||||
(self['component'], self['target'] or '', d)
|
self['_href'] = self['component']
|
||||||
self['_href'] = self['_href'] or '#null'
|
|
||||||
elif self['callback']:
|
elif self['callback']:
|
||||||
returnfalse = "var e = arguments[0] || window.event; e.cancelBubble=true; if (e.stopPropagation) {e.stopPropagation(); e.stopImmediatePropagation(); e.preventDefault();}"
|
self['_data-w2p_method'] = 'POST'
|
||||||
if d and not self['noconfirm']:
|
self['_href'] = self['callback']
|
||||||
self['_onclick'] = "if(confirm(w2p_ajax_confirm_message||'Are you sure you want to delete this object?')){ajax('%s',[],'%s');%s};%s" % \
|
if self['delete'] and not self['noconfirm']:
|
||||||
(self['callback'], self['target'] or '', d, returnfalse)
|
if not self['confirm']:
|
||||||
else:
|
self['_data-w2p_confirm'] = 'default'
|
||||||
self['_onclick'] = "ajax('%s',[],'%s');%sreturn false" % \
|
else:
|
||||||
(self['callback'], self['target'] or '', d)
|
self['_data-w2p_confirm'] = self['confirm']
|
||||||
self['_href'] = self['_href'] or '#null'
|
|
||||||
elif self['cid']:
|
elif self['cid']:
|
||||||
pre = self['pre_call'] + ';' if self['pre_call'] else ''
|
self['_data-w2p_method'] = 'GET'
|
||||||
self['_onclick'] = '%sweb2py_component("%s","%s");%sreturn false;' % \
|
self['_data-w2p_target'] = self['cid']
|
||||||
(pre,self['_href'], self['cid'], d)
|
if self['pre_call']:
|
||||||
|
self['_data-w2p_pre_call'] = self['pre_call']
|
||||||
return DIV.xml(self)
|
return DIV.xml(self)
|
||||||
|
|
||||||
|
|
||||||
class BUTTON(DIV):
|
class BUTTON(DIV):
|
||||||
|
|
||||||
tag = 'button'
|
tag = 'button'
|
||||||
@@ -2481,7 +2481,7 @@ def test():
|
|||||||
|
|
||||||
>>> from validators import *
|
>>> from validators import *
|
||||||
>>> print DIV(A('click me', _href=URL(a='a', c='b', f='c')), BR(), HR(), DIV(SPAN(\"World\"), _class='unknown')).xml()
|
>>> print DIV(A('click me', _href=URL(a='a', c='b', f='c')), BR(), HR(), DIV(SPAN(\"World\"), _class='unknown')).xml()
|
||||||
<div><a href=\"/a/b/c\">click me</a><br /><hr /><div class=\"unknown\"><span>World</span></div></div>
|
<div><a data-w2p_disable_with="default" href="/a/b/c">click me</a><br /><hr /><div class=\"unknown\"><span>World</span></div></div>
|
||||||
>>> print DIV(UL(\"doc\",\"cat\",\"mouse\")).xml()
|
>>> print DIV(UL(\"doc\",\"cat\",\"mouse\")).xml()
|
||||||
<div><ul><li>doc</li><li>cat</li><li>mouse</li></ul></div>
|
<div><ul><li>doc</li><li>cat</li><li>mouse</li></ul></div>
|
||||||
>>> print DIV(UL(\"doc\", LI(\"cat\", _class='feline'), 18)).xml()
|
>>> print DIV(UL(\"doc\", LI(\"cat\", _class='feline'), 18)).xml()
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class TestBareHelpers(unittest.TestCase):
|
|||||||
|
|
||||||
def testA(self):
|
def testA(self):
|
||||||
self.assertEqual(A('<>', _a='1', _b='2').xml(),
|
self.assertEqual(A('<>', _a='1', _b='2').xml(),
|
||||||
'<a a="1" b="2"><></a>')
|
'<a a="1" b="2" data-w2p_disable_with="default"><></a>')
|
||||||
|
|
||||||
def testB(self):
|
def testB(self):
|
||||||
self.assertEqual(B('<>', _a='1', _b='2').xml(),
|
self.assertEqual(B('<>', _a='1', _b='2').xml(),
|
||||||
@@ -209,8 +209,7 @@ class TestBareHelpers(unittest.TestCase):
|
|||||||
class TestData(unittest.TestCase):
|
class TestData(unittest.TestCase):
|
||||||
|
|
||||||
def testAdata(self):
|
def testAdata(self):
|
||||||
self.assertEqual(A('<>', data=dict(abc='<def?asd>', cde='standard'), _a='1', _b='2').xml(),
|
self.assertEqual(A('<>', data=dict(abc='<def?asd>', cde='standard'), _a='1', _b='2').xml(),'<a a="1" b="2" data-abc="<def?asd>" data-cde="standard" data-w2p_disable_with="default"><></a>')
|
||||||
'<a a="1" b="2" data-abc="<def?asd>" data-cde="standard"><></a>')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user