source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/applications/welcome/static/js/web2py.js

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 36.3 KB
Line 
1(function ($, undefined) {
2    /*
3     * Unobtrusive scripting adapter for jQuery, largely taken from
4     * the wonderful https://github.com/rails/jquery-ujs
5     *
6     *
7     * Released under the MIT license
8     *
9     */
10    'use strict';
11    if ($.web2py !== undefined) {
12        $.error('web2py.js has already been loaded!');
13    }
14
15    var FORMDATA_IS_SUPPORTED = typeof(FormData) !== 'undefined';
16    var animateIn = 'fadeIn';
17    // var animateIn = 'slideDown';
18
19    String.prototype.reverse = function () {
20        return this.split('').reverse().join('');
21    };
22    var web2py;
23
24    $.web2py = web2py = {
25
26        isUndefined: function (obj) {
27            /* grabbed from underscore.js */
28            return obj === void 0;
29        },
30        popup: function (url) {
31            /* popup a window */
32            var newwindow = window.open(url, 'name', 'height=400,width=600');
33            if (window.focus) newwindow.focus();
34            return false;
35        },
36        collapse: function (id) {
37            /* toggle an element */
38            $('#' + id).slideToggle();
39        },
40        fade: function (id, value) {
41            /*fade something*/
42            if (value > 0) $('#' + id).hide().fadeIn('slow');
43            else $('#' + id).show().fadeOut('slow');
44        },
45        ajax: function (u, s, t, options) {
46            /*simple ajax function*/
47
48            // set options default value
49            options = typeof options !== 'undefined' ? options : {};
50
51            var query = '';
52            if (typeof s == 'string') {
53                var d = $(s).serialize();
54                if (d) {
55                    query = d;
56                }
57            } else {
58                var pcs = [];
59                if (s !== null && !web2py.isUndefined(s))
60                    for (var i = 0; i < s.length; i++) {
61                        var q = $('[name=' + s[i] + ']').serialize();
62                        if (q) {
63                            pcs.push(q);
64                        }
65                    }
66                if (pcs.length > 0) {
67                    query = pcs.join('&');
68                }
69            }
70
71            // default success action
72            var success_function = function (msg) {
73                if (t) {
74                    if (t == ':eval') eval(msg);
75                    else if (typeof t == 'string') $('#' + t).html(msg);
76                    else t(msg);
77                }
78            };
79
80            // declare success actions as array
81            var success = [success_function];
82
83            // add user success actions
84            if ($.isArray(options.done)){
85                success = $.merge(success, options.done);
86            } else {
87                success.push(options.done);
88            }
89
90            // default jquery ajax options
91            var ajax_options = {
92                type: 'POST',
93                url: u,
94                data: query,
95                success: success
96            };
97
98            //remove custom "done" option if exists
99            delete options.done;
100
101            // merge default ajax options with user custom options
102            for (var attrname in options) {
103                    ajax_options[attrname] = options[attrname];
104            }
105
106            // call ajax function
107            $.ajax(ajax_options);
108        },
109        ajax_fields: function (target) {
110            /*
111             *this attaches something to a newly loaded fragment/page
112             * Ideally all events should be bound to the document, so we can avoid calling
113             * this over and over... all will be bound to the document
114             */
115            /*adds btn class to buttons*/
116            $('button:not([class^="btn"])', target).addClass('btn');
117            $(
118                'form input[type="submit"]:not([class^="btn"]), form input[type="button"]:not([class^="btn"])',
119                target).addClass('btn');
120            /* javascript for PasswordWidget*/
121            $('input[type=password][data-w2p_entropy]', target).each(function () {
122                web2py.validate_entropy($(this));
123            });
124            /* javascript for ListWidget*/
125            $('ul.w2p_list', target).each(function () {
126                function pe(ul, e) {
127                    var new_line = ml(ul);
128                    rel(ul);
129                    if ($(e.target).parent().is(':visible')) {
130                        /* make sure we didn't delete the element before we insert after */
131                        new_line.insertAfter($(e.target).parent());
132                    } else {
133                        /* the line we clicked on was deleted, just add to end of list */
134                        new_line.appendTo(ul);
135                    }
136                    new_line.find(':text').focus();
137                    return false;
138                }
139
140                function rl(ul, e) {
141                    if ($(ul).children().length > 1) {
142                        /* only remove if we have more than 1 item so the list is never empty */
143                        $(e.target).parent().remove();
144                    }
145                }
146
147                function ml(ul) {
148                    /* clone the first field */
149                    var line = $(ul).find('li:first').clone(true);
150                    line.find(':text').val('');
151                    return line;
152                }
153
154                function rel(ul) {
155                    /* keep only as many as needed*/
156                    $(ul).find('li').each(function () {
157                        var trimmed = $.trim($(this.firstChild).val());
158                        if (trimmed === '') $(this).remove();
159                        else $(this.firstChild).val(trimmed);
160                    });
161                }
162                var ul = this;
163                $(ul).find(':text').after('<a href="#">+</a>&nbsp;<a href="#">-</a>').keypress(
164                    function (e) {
165                        return (e.which == 13) ? pe(ul, e) : true;
166                    }).next().click(function (e) {
167                    pe(ul, e);
168                    e.preventDefault();
169                }).next().click(function (e) {
170                    rl(ul, e);
171                    e.preventDefault();
172                });
173            });
174        },
175        ajax_init: function (target) {
176            /*called whenever a fragment gets loaded */
177            $('.w2p_hidden', target).hide();
178            web2py.manage_errors(target);
179            web2py.ajax_fields(target);
180            web2py.show_if_handler(target);
181            web2py.component_handler(target);
182        },
183        /* manage errors in forms */
184        manage_errors: function (target) {
185            $('div.error', target).hide()[animateIn]('slow');
186        },
187        after_ajax: function (xhr) {
188            /* called whenever an ajax request completes */
189            var command = xhr.getResponseHeader('web2py-component-command');
190            var flash = xhr.getResponseHeader('web2py-component-flash');
191            if (command !== null) {
192                eval(decodeURIComponent(command));
193            }
194            if (flash) {
195                web2py.flash(decodeURIComponent(flash));
196            }
197        },
198        event_handlers: function () {
199            /*
200             * This is called once for page
201             * Ideally it should bound all the things that are needed
202             * and require no dom manipulations
203             */
204            var doc = $(document);
205            doc.on('click', '.w2p_flash', function (event) {
206                event.preventDefault();
207                var t = $(this);
208                if (t.css('top') == '0px') t.slideUp('slow');
209                else t.fadeOut();
210            });
211            doc.on('keyup', 'input.integer', function () {
212                var nvalue = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
213                if (this.value != nvalue) this.value = nvalue;
214            });
215            doc.on('keyup', 'input.double, input.decimal', function () {
216                var nvalue = this.value.reverse().replace(
217                    /[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
218                if (this.value != nvalue) this.value = nvalue;
219            });
220            var confirm_message = !web2py.isUndefined(w2p_ajax_confirm_message) ? w2p_ajax_confirm_message :
221                'Are you sure you want to delete this object?';
222            doc.on('click', 'input[type="checkbox"].delete', function () {
223                if (this.checked)
224                    if (!web2py.confirm(confirm_message)) this.checked = false;
225            });
226            var datetime_format = !web2py.isUndefined(w2p_ajax_datetime_format) ? w2p_ajax_datetime_format :
227                '%Y-%m-%d %H:%M:%S';
228            doc.on('click', 'input.datetime', function () {
229                var tformat = $(this).data('w2p_datetime_format');
230                var active = $(this).data('w2p_datetime');
231                var format = !web2py.isUndefined(tformat) ? tformat : datetime_format;
232                if (active === undefined) {
233                    Calendar.setup({
234                        inputField: this,
235                        ifFormat: format,
236                        showsTime: true,
237                        timeFormat: '24'
238                    });
239                    $(this).attr('autocomplete', 'off');
240                    $(this).data('w2p_datetime', 1);
241                    $(this).trigger('click');
242                }
243            });
244            var date_format = !web2py.isUndefined(w2p_ajax_date_format) ? w2p_ajax_date_format : '%Y-%m-%d';
245            doc.on('click', 'input.date', function () {
246                var tformat = $(this).data('w2p_date_format');
247                var active = $(this).data('w2p_date');
248                var format = !web2py.isUndefined(tformat) ? tformat : date_format;
249                if (active === undefined) {
250                    Calendar.setup({
251                        inputField: this,
252                        ifFormat: format,
253                        showsTime: false
254                    });
255                    $(this).data('w2p_date', 1);
256                    $(this).attr('autocomplete', 'off');
257                    $(this).trigger('click');
258                }
259            });
260            doc.on('focus', 'input.time', function () {
261                var active = $(this).data('w2p_time');
262                if (web2py.isUndefined(active)) {
263                    $(this).timeEntry({
264                        spinnerImage: ''
265                    }).attr('autocomplete', 'off');
266                    $(this).data('w2p_time', 1);
267                }
268            });
269            /* help preventing double form submission for normal form (not LOADed) */
270            $(doc).on('submit', 'form', function (e) {
271                var submit_buttons = $(this).find(web2py.formInputClickSelector);
272                submit_buttons.each(function() {
273                    web2py.disableElement($(this));
274                })
275                /* safeguard in case the form doesn't trigger a refresh,
276                see https://github.com/web2py/web2py/issues/1100 */
277                setTimeout(function () {
278                    submit_buttons.each(function() {
279                        web2py.enableElement($(this));
280                    });
281                }, 5000);
282            });
283            doc.ajaxSuccess(function (e, xhr) {
284                var redirect = xhr.getResponseHeader('web2py-redirect-location');
285                if (redirect !== null) {
286                    if (!redirect.endsWith('#')) {
287                        window.location.href = redirect;
288                    } else {
289                        window.location.reload();
290                    }
291                }
292                /* run this here only if this Ajax request is NOT for a web2py component. */
293                if (xhr.getResponseHeader('web2py-component-content') === null) {
294                    web2py.after_ajax(xhr);
295                }
296            });
297
298            doc.ajaxError(function (e, xhr, settings, exception) {
299                /*personally I don't like it.
300                 *if there's an error it it flashed and can be removed
301                 *as any other message
302                 *doc.off('click', '.w2p_flash')
303                 */
304                switch (xhr.status) {
305                case 500:
306                    web2py.flash(ajax_error_500);
307                }
308            });
309
310        },
311        trap_form: function (action, target) {
312            /* traps any LOADed form */
313            $('#' + target + ' form').each(function () {
314                var form = $(this);
315                if (form.hasClass('no_trap')) {
316                    return;
317                }
318
319                var w2p_target = $(this).attr('data-w2p_target');
320                if (web2py.isUndefined(w2p_target) || w2p_target === false) {
321                    form.attr('data-w2p_target', target);
322                } else {
323                    target = w2p_target;
324                }
325
326                var url = form.attr('action');
327                if ((url === '') || (url === '#') || web2py.isUndefined(url)) {
328                    /* form has no action. Use component url. */
329                    url = action;
330                }
331
332                form.submit(function (e) {
333                    web2py.disableElement(form.find(web2py.formInputClickSelector));
334                    web2py.hide_flash();
335
336                    var formData;
337                    if (FORMDATA_IS_SUPPORTED) {
338                        formData = new FormData(form[0]); // Allows file uploads.
339                    } else {
340                        formData = form.serialize(); // Fallback for older browsers.
341                    }
342                    web2py.ajax_page('post', url, formData, target);
343
344                    e.preventDefault();
345                });
346                form.on('click', web2py.formInputClickSelector, function (e) {
347                    e.preventDefault();
348                    var input_name = $(this).attr('name');
349                    if (!web2py.isUndefined(input_name)) {
350                        $('<input type="hidden" />').attr('name', input_name)
351                            .attr('value', $(this).val()).appendTo(form);
352                    }
353                    form.trigger('submit');
354                });
355            });
356        },
357        ajax_page: function (method, action, data, target, element) {
358            /* element is a new parameter, but should be put be put in front */
359            if (web2py.isUndefined(element)) element = $(document);
360            /* if target is not there, fill it with something that there isn't in the page*/
361            if (web2py.isUndefined(target) || target === '') target = 'w2p_none';
362
363            /* processData and contentType must be set to false when passing a FormData
364               object to jQuery.ajax. */
365            var isFormData = Object.prototype.toString.call(data) === '[object FormData]';
366            var contentType = isFormData ? false : 'application/x-www-form-urlencoded; charset=UTF-8';
367            if (web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */
368                $.ajax({
369                    'type': method,
370                    'url': action,
371                    'data': data,
372                    'processData': !isFormData,
373                    'contentType': contentType,
374                    'xhr': function() {
375                        var xhr = new window.XMLHttpRequest();
376
377                        xhr.upload.addEventListener("progress", function(evt) {
378                            if (evt.lengthComputable) {
379                                var percentComplete = evt.loaded / evt.total;
380                                percentComplete = parseInt(percentComplete * 100);
381                                web2py.fire(element, 'w2p:uploadProgress', [percentComplete], target);
382
383                                if (percentComplete === 100) {
384                                    web2py.fire(element, 'w2p:uploadComplete', [], target);
385                                }
386
387                            }
388                        }, false);
389
390                        return xhr;
391                    },
392                    'beforeSend': function (xhr, settings) {
393                        xhr.setRequestHeader('web2py-component-location', document.location);
394                        xhr.setRequestHeader('web2py-component-element', target);
395                        web2py.fire(element, 'w2p:componentBegin', [xhr, settings], target);
396                        return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
397                    },
398                    'success': function (data, status, xhr) {
399                        /*bummer for form submissions....the element is not there after complete
400                         *because it gets replaced by the new response....
401                         */
402                        web2py.fire(element, 'ajax:success', [data, status, xhr], target);
403                    },
404                    'error': function (xhr, status, error) {
405                        /*bummer for form submissions....in addition to the element being not there after
406                         *complete because it gets replaced by the new response, standard form
407                         *handling just returns the same status code for good and bad
408                         *form submissions (i.e. that triggered a validator error)
409                         */
410                        web2py.fire(element, 'ajax:error', [xhr, status, error], target);
411                    },
412                    'complete': function (xhr, status) {
413                        web2py.fire(element, 'ajax:complete', [xhr, status], target);
414                        web2py.updatePage(xhr, target); /* Parse and load the html received */
415                        web2py.trap_form(action, target);
416                        web2py.ajax_init('#' + target);
417                        web2py.after_ajax(xhr);
418                        web2py.fire(element, 'w2p:componentComplete', [xhr, status], target); // Let us know the component is finished loading
419                    }
420                });
421            }
422        },
423        component: function (action, target, timeout, times, el) {
424            /* element is a new parameter, but should be put in front */
425            $(function () {
426                var jelement = $('#' + target);
427                var element = jelement.get(0);
428                var statement = 'jQuery("#' + target + '").get(0).reload();';
429                element.reload = function () {
430                    /* Continue if times is Infinity or
431                     * the times limit is not reached
432                     */
433                    if (element.reload_check()) {
434                        web2py.ajax_page('get', action, null, target, el);
435                    }
436                };
437                /* Method to check timing limit */
438                element.reload_check = function () {
439                    if (jelement.hasClass('w2p_component_stop')) {
440                        clearInterval(this.timing);
441                        return false;
442                    }
443                    if (this.reload_counter == Infinity) {
444                        return true;
445                    } else {
446                        if (!isNaN(this.reload_counter)) {
447                            this.reload_counter -= 1;
448                            if (this.reload_counter < 0) {
449                                if (!this.run_once) {
450                                    clearInterval(this.timing);
451                                    return false;
452                                }
453                            } else {
454                                return true;
455                            }
456                        }
457                    }
458                    return false;
459                };
460                if (!isNaN(timeout)) {
461                    element.timeout = timeout;
462                    element.reload_counter = times;
463                    if (times > 1) {
464                        /* Multiple or infinite reload
465                         * Run first iteration
466                         */
467                        web2py.ajax_page('get', action, null, target, el);
468                        element.run_once = false;
469                        element.timing = setInterval(statement, timeout);
470                        element.reload_counter -= 1;
471                    } else if (times == 1) {
472                        /* Run once with timeout */
473                        element.run_once = true;
474                        element.setTimeout = setTimeout;
475                        element.timing = setTimeout(statement, timeout);
476                    }
477                } else {
478                    /* run once (no timeout specified) */
479                    element.reload_counter = Infinity;
480                    web2py.ajax_page('get', action, null, target, el);
481                }
482            });
483        },
484        updatePage: function (xhr, target) {
485            var t = $('#' + target);
486            var html = $.parseHTML(xhr.responseText, document, true);
487            var title_elements = $(html).filter('title').add($(html).find('title'));
488            var title = title_elements.last().text();
489            if (title) {
490                title_elements.remove(); /* Remove any title elements from the response */
491                document.title = $.trim(title); /* Set the new document title */
492            }
493            var content = xhr.getResponseHeader('web2py-component-content');
494            if (content == 'prepend') t.prepend(xhr.responseText);
495            else if (content == 'append') t.append(xhr.responseText);
496            else if (content != 'hide') t.html(html);
497        },
498        calc_entropy: function (mystring) {
499            /* calculate a simple entropy for a given string */
500            var csets = new Array(
501                'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
502                '0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
503                '0123456789abcdefghijklmnopqrstuvwxyz');
504            var score = 0,
505                other = {},
506                seen = {},
507                lastset = null,
508                mystringlist = mystring.split('');
509            for (var i = 0; i < mystringlist.length; i++) { /* classify this character */
510                var c = mystringlist[i],
511                    inset = 5;
512                for (var j = 0; j < csets.length; j++)
513                    if (csets[j].indexOf(c) != -1) {
514                        inset = j;
515                        break;
516                    }
517                    /*calculate effect of character on alphabet size */
518                if (!(inset in seen)) {
519                    seen[inset] = 1;
520                    score += csets[inset].length;
521                } else if (!(c in other)) {
522                    score += 1;
523                    other[c] = 1;
524                }
525                if (inset != lastset) {
526                    score += 1;
527                    lastset = inset;
528                }
529            }
530            var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
531            return Math.round(entropy * 100) / 100;
532        },
533        validate_entropy: function (myfield, req_entropy) {
534            if (!web2py.isUndefined(myfield.data('w2p_entropy'))) req_entropy = myfield.data('w2p_entropy');
535            var validator = function () {
536                var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
537                var r = 0,
538                    g = 0,
539                    b = 0,
540                    rs = function (x) {
541                        return Math.round(x * 15).toString(16);
542                    };
543                if (v <= 0.5) {
544                    r = 1.0;
545                    g = 2.0 * v;
546                } else {
547                    r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
548                    g = 1.0;
549                }
550                var color = '#' + rs(r) + rs(g) + rs(b);
551                myfield.css('background-color', color);
552                var entropy_callback = myfield.data('entropy_callback');
553                if (entropy_callback) entropy_callback(v);
554            };
555            if (!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator)
556                .addClass('entropy_check');
557        },
558        web2py_websocket: function (url, onmessage, onopen, onclose) {
559            if ('WebSocket' in window) {
560                var ws = new WebSocket(url);
561                ws.onopen = onopen ? onopen : (function () {});
562                ws.onmessage = onmessage;
563                ws.onclose = onclose ? onclose : (function () {});
564                return true; /* supported */
565            } else return false; /* not supported */
566        },
567        /* new from here */
568        /* Form input elements bound by web2py.js */
569        formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
570        /* Form input elements disabled during form submission */
571        disableSelector: 'input, button, textarea, select',
572        /* Form input elements re-enabled after form submission */
573        enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
574        /* Triggers an event on an element and returns false if the event result is false */
575        fire: function (obj, type, data, target) {
576            var event = $.Event(type, {
577                'containerTarget': $('#' + target)[0]
578            });
579            obj.trigger(event, data);
580            return event.result !== false;
581        },
582        /* Helper function, needed to provide consistent behavior in IE */
583        stopEverything: function (e) {
584            $(e.target).trigger('w2p:everythingStopped');
585            e.stopImmediatePropagation();
586            return false;
587        },
588        confirm: function (message) {
589            return confirm(message);
590        },
591        /* replace element's html with the 'data-disable-with' after storing original html
592         * and prevent clicking on it */
593        disableElement: function (el) {
594            if (!web2py.isUndefined(el.data('w2p_disable'))) {
595                return false;
596            }
597            el.addClass('disabled');
598            var method = el.is('input') ? 'val' : 'html';
599            //method = el.attr('name') ? 'html' : 'val';
600            var disable_with_message = (!web2py.isUndefined(w2p_ajax_disable_with_message)) ?
601                w2p_ajax_disable_with_message : 'Working...';
602            /*store enabled state if not already disabled */
603            if (web2py.isUndefined(el.data('w2p_enable_with'))) {
604                el.data('w2p_enable_with', el[method]());
605            }
606            /*if you don't want to see "working..." on buttons, replace the following
607             * two lines with this one
608             * el.data('w2p_disable_with', el[method]());
609             */
610            if ((el.data('w2p_disable_with') == 'default') || (web2py.isUndefined(el.data(
611                    'w2p_disable_with')))) {
612                el.data('w2p_disable_with', disable_with_message);
613            }
614
615            /* set to disabled state*/
616            el[method](el.data('w2p_disable_with'));
617
618            el.bind('click.w2pDisable', function (e) { /* prevent further clicking*/
619                return web2py.stopEverything(e);
620            });
621        },
622
623        /* restore element to its original state which was disabled by 'disableElement' above*/
624        enableElement: function (el) {
625            var method = el.is('input') ? 'val' : 'html';
626            if (!web2py.isUndefined(el.data('w2p_enable_with'))) {
627                /* set to old enabled state */
628                el[method](el.data('w2p_enable_with'));
629                el.removeData('w2p_enable_with');
630            }
631            el.removeClass('disabled');
632            el.unbind('click.w2pDisable');
633        },
634        /*convenience wrapper, internal use only */
635        simple_component: function (action, target, element) {
636            web2py.component(action, target, 0, 1, element);
637        },
638        /*helper for flash messages*/
639        flash: function (message, status) {
640            var flash = $('.w2p_flash');
641            web2py.hide_flash();
642            flash.text(message).addClass(status);
643            if (flash.html()) flash.append('<span id="closeflash"> &times; </span>')[animateIn]();
644        },
645        hide_flash: function () {
646            $('.w2p_flash').fadeOut(0).html('');
647        },
648        show_if_handler: function (target) {
649            var triggers = {};
650            var show_if = function () {
651                var t = $(this);
652                var id = t.attr('id');
653                t.attr('value', t.val());
654                for (var k = 0; k < triggers[id].length; k++) {
655                    var dep = $('#' + triggers[id][k], target);
656                    var tr = $('#' + triggers[id][k] + '__row', target);
657                    if (t.is(dep.attr('data-show-if'))) tr[animateIn]();
658                    else tr.hide();
659                }
660            };
661            $('[data-show-trigger]', target).each(function () {
662                var name = $(this).attr('data-show-trigger');
663                // The field exists only when creating/editing a row
664                if ($('#' + name).length) {
665                    if (!triggers[name]) triggers[name] = [];
666                    triggers[name].push($(this).attr('id'));
667                }
668            });
669            for (var name in triggers) {
670                $('#' + name, target).change(show_if).keyup(show_if);
671                show_if.call($('#' + name, target));
672            }
673        },
674        component_handler: function (target) {
675            $('div[data-w2p_remote]', target).each(function () {
676                var remote, times, timeout, target;
677                var el = $(this);
678                remote = el.data('w2p_remote');
679                times = el.data('w2p_times');
680                timeout = el.data('w2p_timeout');
681                target = el.attr('id');
682                web2py.component(remote, target, timeout, times, $(this));
683            });
684        },
685        a_handler: function (el, e) {
686            e.preventDefault();
687            var method = el.data('w2p_method');
688            var action = el.attr('href');
689            var target = el.data('w2p_target');
690            var confirm_message = el.data('w2p_confirm');
691
692            var pre_call = el.data('w2p_pre_call');
693            if (!web2py.isUndefined(pre_call)) {
694                eval(pre_call);
695            }
696            if (confirm_message) {
697                if (confirm_message == 'default') {
698                    confirm_message = !web2py.isUndefined(w2p_ajax_confirm_message) ? 
699                    w2p_ajax_confirm_message : 'Are you sure you want to delete this object?';
700                }
701                if (!web2py.confirm(confirm_message)) {
702                    web2py.stopEverything(e);
703                    return;
704                }
705            }
706            if (web2py.isUndefined(target)) {
707                if (method == 'GET') {
708                    web2py.ajax_page('get', action, [], '', el);
709                } else if (method == 'POST') {
710                    web2py.ajax_page('post', action, [], '', el);
711                }
712            } else {
713                if (method == 'GET') {
714                    web2py.ajax_page('get', action, [], target, el);
715                } else if (method == 'POST') {
716                    web2py.ajax_page('post', action, [], target, el);
717                }
718            }
719        },
720        a_handlers: function () {
721            var el = $(document);
722            el.on('click', 'a[data-w2p_method]', function (e) {
723                web2py.a_handler($(this), e);
724            });
725            /* removal of element should happen only on success */
726            el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function () {
727                var el = $(this);
728                var toremove = el.data('w2p_remove');
729                if (!web2py.isUndefined(toremove)) {
730                    toremove = el.closest(toremove);
731                    if (!toremove.length) {
732                        /*this enables removal of whatever selector if a closest is not found */
733                        toremove = $(toremove);
734                    }
735                    toremove.remove();
736                }
737            });
738            el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function () {
739                web2py.disableElement($(this));
740            });
741            /*re-enable click on completion*/
742            el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function () {
743                web2py.enableElement($(this));
744            });
745        },
746        /* Disables form elements:
747        - Does not disable elements with 'data-w2p_disable' attribute
748        - Caches element value in 'w2p_enable_with' data store
749        - Replaces element text with value of 'data-w2p_disable_with' attribute
750        - Sets disabled property to true
751        */
752        disableFormElements: function (form) {
753            form.find(web2py.disableSelector).each(function () {
754                var element = $(this),
755                    method = element.is('button') ? 'html' : 'val';
756                var disable_with = element.data('w2p_disable_with');
757                var disable = element.data('w2p_disable');
758                if (!web2py.isUndefined(disable)) {
759                    return false;
760                }
761                if (!element.is(':file')) { // Altering file input values is not allowed.
762                    if (web2py.isUndefined(disable_with)) {
763                        element.data('w2p_disable_with', element[method]());
764                    }
765                    if (web2py.isUndefined(element.data('w2p_enable_with'))) {
766                        element.data('w2p_enable_with', element[method]());
767                    }
768                    element[method](element.data('w2p_disable_with'));
769                }
770                element.prop('disabled', true);
771            });
772        },
773
774        /* Re-enables disabled form elements:
775        - Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`)
776        - Sets disabled property to false
777        */
778        enableFormElements: function (form) {
779            form.find(web2py.enableSelector).each(function () {
780                var element = $(this),
781                    method = element.is('button') ? 'html' : 'val';
782                if (element.data('w2p_enable_with')) {
783                    element[method](element.data('w2p_enable_with'));
784                    element.removeData('w2p_enable_with');
785                }
786                element.prop('disabled', false);
787            });
788        },
789        form_handlers: function () {
790            var el = $(document);
791            el.on('ajax:beforeSend', 'form[data-w2p_target]', function () {
792                web2py.disableFormElements($(this));
793            });
794            el.on('ajax:complete', 'form[data-w2p_target]', function () {
795                web2py.enableFormElements($(this));
796            });
797        },
798        /* Invalidate and force reload of a web2py component
799         */
800        invalidate: function (target) {
801            $('div[data-w2p_remote]', target).each(function () {
802                var el = $('#' + $(this).attr('id')).get(0);
803                if (!web2py.isUndefined(el.timing)) { // Block triggering regular routines
804                    clearInterval(el.timing);
805                }
806            });
807            $.web2py.component_handler(target);
808        },
809        main_hook: function () {
810            var flash = $('.w2p_flash');
811            flash.hide();
812            if (flash.html()) web2py.flash(flash.html());
813            web2py.ajax_init(document);
814            web2py.event_handlers();
815            web2py.a_handlers();
816            web2py.form_handlers();
817        }
818    };
819    /*end of functions */
820    /*main hook*/
821    $(function () {
822        web2py.main_hook();
823    });
824
825})(jQuery);
826
827/* compatibility code - start */
828ajax = jQuery.web2py.ajax;
829web2py_component = jQuery.web2py.component;
830web2py_websocket = jQuery.web2py.web2py_websocket;
831web2py_ajax_page = jQuery.web2py.ajax_page;
832/*needed for IS_STRONG(entropy)*/
833web2py_validate_entropy = jQuery.web2py.validate_entropy;
834/*needed for crud.search and SQLFORM.grid's search*/
835web2py_ajax_fields = jQuery.web2py.ajax_fields;
836/*used for LOAD(ajax=False)*/
837web2py_trap_form = jQuery.web2py.trap_form;
838
839/*undocumented - rare*/
840popup = jQuery.web2py.popup;
841collapse = jQuery.web2py.collapse;
842fade = jQuery.web2py.fade;
843
844/* internals - shouldn't be needed
845web2py_ajax_init = jQuery.web2py.ajax_init;
846web2py_event_handlers = jQuery.web2py.event_handlers;
847web2py_trap_link = jQuery.web2py.trap_link;
848web2py_calc_entropy = jQuery.web2py.calc_entropy;
849*/
850/* compatibility code - end*/
Note: See TracBrowser for help on using the repository browser.