source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/applications/admin/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: 35.4 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                    window.location = redirect;
287                    window.location.reload(); // Force reload even with anchors
288                }
289                /* run this here only if this Ajax request is NOT for a web2py component. */
290                if (xhr.getResponseHeader('web2py-component-content') === null) {
291                    web2py.after_ajax(xhr);
292                }
293            });
294
295            doc.ajaxError(function (e, xhr, settings, exception) {
296                /*personally I don't like it.
297                 *if there's an error it it flashed and can be removed
298                 *as any other message
299                 *doc.off('click', '.w2p_flash')
300                 */
301                switch (xhr.status) {
302                case 500:
303                    web2py.flash(ajax_error_500);
304                }
305            });
306
307        },
308        trap_form: function (action, target) {
309            /* traps any LOADed form */
310            $('#' + target + ' form').each(function () {
311                var form = $(this);
312                if (form.hasClass('no_trap')) {
313                    return;
314                }
315
316                var w2p_target = $(this).attr('data-w2p_target');
317                if (web2py.isUndefined(w2p_target) || w2p_target === false) {
318                    form.attr('data-w2p_target', target);
319                } else {
320                    target = w2p_target;
321                }
322
323                var url = form.attr('action');
324                if ((url === '') || (url === '#') || web2py.isUndefined(url)) {
325                    /* form has no action. Use component url. */
326                    url = action;
327                }
328
329                form.submit(function (e) {
330                    web2py.disableElement(form.find(web2py.formInputClickSelector));
331                    web2py.hide_flash();
332
333                    var formData;
334                    if (FORMDATA_IS_SUPPORTED) {
335                        formData = new FormData(form[0]); // Allows file uploads.
336                    } else {
337                        formData = form.serialize(); // Fallback for older browsers.
338                    }
339                    web2py.ajax_page('post', url, formData, target, form);
340
341                    e.preventDefault();
342                });
343                form.on('click', web2py.formInputClickSelector, function (e) {
344                    e.preventDefault();
345                    var input_name = $(this).attr('name');
346                    if (!web2py.isUndefined(input_name)) {
347                        $('<input type="hidden" />').attr('name', input_name)
348                            .attr('value', $(this).val()).appendTo(form);
349                    }
350                    form.trigger('submit');
351                });
352            });
353        },
354        ajax_page: function (method, action, data, target, element) {
355            /* element is a new parameter, but should be put be put in front */
356            if (web2py.isUndefined(element)) element = $(document);
357            /* if target is not there, fill it with something that there isn't in the page*/
358            if (web2py.isUndefined(target) || target === '') target = 'w2p_none';
359
360            /* processData and contentType must be set to false when passing a FormData
361               object to jQuery.ajax. */
362            var isFormData = Object.prototype.toString.call(data) === '[object FormData]';
363            var contentType = isFormData ? false : 'application/x-www-form-urlencoded; charset=UTF-8';
364            if (web2py.fire(element, 'ajax:before', null, target)) { /*test a usecase, should stop here if returns false */
365                $.ajax({
366                    'type': method,
367                    'url': action,
368                    'data': data,
369                    'processData': !isFormData,
370                    'contentType': contentType,
371                    'beforeSend': function (xhr, settings) {
372                        xhr.setRequestHeader('web2py-component-location', document.location);
373                        xhr.setRequestHeader('web2py-component-element', target);
374                        web2py.fire(element, 'w2p:componentBegin', [xhr, settings], target);
375                        return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
376                    },
377                    'success': function (data, status, xhr) {
378                        /*bummer for form submissions....the element is not there after complete
379                         *because it gets replaced by the new response....
380                         */
381                        web2py.fire(element, 'ajax:success', [data, status, xhr], target);
382                    },
383                    'error': function (xhr, status, error) {
384                        /*bummer for form submissions....in addition to the element being not there after
385                         *complete because it gets replaced by the new response, standard form
386                         *handling just returns the same status code for good and bad
387                         *form submissions (i.e. that triggered a validator error)
388                         */
389                        web2py.fire(element, 'ajax:error', [xhr, status, error], target);
390                    },
391                    'complete': function (xhr, status) {
392                        web2py.fire(element, 'ajax:complete', [xhr, status], target);
393                        web2py.updatePage(xhr, target); /* Parse and load the html received */
394                        web2py.trap_form(action, target);
395                        web2py.ajax_init('#' + target);
396                        web2py.after_ajax(xhr);
397                        web2py.fire(element, 'w2p:componentComplete', [xhr, status], target); // Let us know the component is finished loading
398                    }
399                });
400            }
401        },
402        component: function (action, target, timeout, times, el) {
403            /* element is a new parameter, but should be put in front */
404            $(function () {
405                var jelement = $('#' + target);
406                var element = jelement.get(0);
407                var statement = 'jQuery("#' + target + '").get(0).reload();';
408                element.reload = function () {
409                    /* Continue if times is Infinity or
410                     * the times limit is not reached
411                     */
412                    if (element.reload_check()) {
413                        web2py.ajax_page('get', action, null, target, el);
414                    }
415                };
416                /* Method to check timing limit */
417                element.reload_check = function () {
418                    if (jelement.hasClass('w2p_component_stop')) {
419                        clearInterval(this.timing);
420                        return false;
421                    }
422                    if (this.reload_counter == Infinity) {
423                        return true;
424                    } else {
425                        if (!isNaN(this.reload_counter)) {
426                            this.reload_counter -= 1;
427                            if (this.reload_counter < 0) {
428                                if (!this.run_once) {
429                                    clearInterval(this.timing);
430                                    return false;
431                                }
432                            } else {
433                                return true;
434                            }
435                        }
436                    }
437                    return false;
438                };
439                if (!isNaN(timeout)) {
440                    element.timeout = timeout;
441                    element.reload_counter = times;
442                    if (times > 1) {
443                        /* Multiple or infinite reload
444                         * Run first iteration
445                         */
446                        web2py.ajax_page('get', action, null, target, el);
447                        element.run_once = false;
448                        element.timing = setInterval(statement, timeout);
449                        element.reload_counter -= 1;
450                    } else if (times == 1) {
451                        /* Run once with timeout */
452                        element.run_once = true;
453                        element.setTimeout = setTimeout;
454                        element.timing = setTimeout(statement, timeout);
455                    }
456                } else {
457                    /* run once (no timeout specified) */
458                    element.reload_counter = Infinity;
459                    web2py.ajax_page('get', action, null, target, el);
460                }
461            });
462        },
463        updatePage: function (xhr, target) {
464            var t = $('#' + target);
465            var html = $.parseHTML(xhr.responseText, document, true);
466            var title_elements = $(html).filter('title').add($(html).find('title'));
467            var title = title_elements.last().text();
468            if (title) {
469                title_elements.remove(); /* Remove any title elements from the response */
470                document.title = $.trim(title); /* Set the new document title */
471            }
472            var content = xhr.getResponseHeader('web2py-component-content');
473            if (content == 'prepend') t.prepend(xhr.responseText);
474            else if (content == 'append') t.append(xhr.responseText);
475            else if (content != 'hide') t.html(html);
476        },
477        calc_entropy: function (mystring) {
478            /* calculate a simple entropy for a given string */
479            var csets = new Array(
480                'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
481                '0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
482                '0123456789abcdefghijklmnopqrstuvwxyz');
483            var score = 0,
484                other = {},
485                seen = {},
486                lastset = null,
487                mystringlist = mystring.split('');
488            for (var i = 0; i < mystringlist.length; i++) { /* classify this character */
489                var c = mystringlist[i],
490                    inset = 5;
491                for (var j = 0; j < csets.length; j++)
492                    if (csets[j].indexOf(c) != -1) {
493                        inset = j;
494                        break;
495                    }
496                    /*calculate effect of character on alphabet size */
497                if (!(inset in seen)) {
498                    seen[inset] = 1;
499                    score += csets[inset].length;
500                } else if (!(c in other)) {
501                    score += 1;
502                    other[c] = 1;
503                }
504                if (inset != lastset) {
505                    score += 1;
506                    lastset = inset;
507                }
508            }
509            var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
510            return Math.round(entropy * 100) / 100;
511        },
512        validate_entropy: function (myfield, req_entropy) {
513            if (!web2py.isUndefined(myfield.data('w2p_entropy'))) req_entropy = myfield.data('w2p_entropy');
514            var validator = function () {
515                var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
516                var r = 0,
517                    g = 0,
518                    b = 0,
519                    rs = function (x) {
520                        return Math.round(x * 15).toString(16);
521                    };
522                if (v <= 0.5) {
523                    r = 1.0;
524                    g = 2.0 * v;
525                } else {
526                    r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
527                    g = 1.0;
528                }
529                var color = '#' + rs(r) + rs(g) + rs(b);
530                myfield.css('background-color', color);
531                var entropy_callback = myfield.data('entropy_callback');
532                if (entropy_callback) entropy_callback(v);
533            };
534            if (!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator)
535                .addClass('entropy_check');
536        },
537        web2py_websocket: function (url, onmessage, onopen, onclose) {
538            if ('WebSocket' in window) {
539                var ws = new WebSocket(url);
540                ws.onopen = onopen ? onopen : (function () {});
541                ws.onmessage = onmessage;
542                ws.onclose = onclose ? onclose : (function () {});
543                return true; /* supported */
544            } else return false; /* not supported */
545        },
546        /* new from here */
547        /* Form input elements bound by web2py.js */
548        formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
549        /* Form input elements disabled during form submission */
550        disableSelector: 'input, button, textarea, select',
551        /* Form input elements re-enabled after form submission */
552        enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
553        /* Triggers an event on an element and returns false if the event result is false */
554        fire: function (obj, type, data, target) {
555            var event = $.Event(type, {
556                'containerTarget': $('#' + target)[0]
557            });
558            obj.trigger(event, data);
559            return event.result !== false;
560        },
561        /* Helper function, needed to provide consistent behavior in IE */
562        stopEverything: function (e) {
563            $(e.target).trigger('w2p:everythingStopped');
564            e.stopImmediatePropagation();
565            return false;
566        },
567        confirm: function (message) {
568            return confirm(message);
569        },
570        /* replace element's html with the 'data-disable-with' after storing original html
571         * and prevent clicking on it */
572        disableElement: function (el) {
573            if (!web2py.isUndefined(el.data('w2p_disable'))) {
574                return false;
575            }
576            el.addClass('disabled');
577            var method = el.is('input') ? 'val' : 'html';
578            //method = el.attr('name') ? 'html' : 'val';
579            var disable_with_message = (!web2py.isUndefined(w2p_ajax_disable_with_message)) ?
580                w2p_ajax_disable_with_message : 'Working...';
581            /*store enabled state if not already disabled */
582            if (web2py.isUndefined(el.data('w2p_enable_with'))) {
583                el.data('w2p_enable_with', el[method]());
584            }
585            /*if you don't want to see "working..." on buttons, replace the following
586             * two lines with this one
587             * el.data('w2p_disable_with', el[method]());
588             */
589            if ((el.data('w2p_disable_with') == 'default') || (web2py.isUndefined(el.data(
590                    'w2p_disable_with')))) {
591                el.data('w2p_disable_with', disable_with_message);
592            }
593
594            /* set to disabled state*/
595            el[method](el.data('w2p_disable_with'));
596
597            el.bind('click.w2pDisable', function (e) { /* prevent further clicking*/
598                return web2py.stopEverything(e);
599            });
600        },
601
602        /* restore element to its original state which was disabled by 'disableElement' above*/
603        enableElement: function (el) {
604            var method = el.is('input') ? 'val' : 'html';
605            if (!web2py.isUndefined(el.data('w2p_enable_with'))) {
606                /* set to old enabled state */
607                el[method](el.data('w2p_enable_with'));
608                el.removeData('w2p_enable_with');
609            }
610            el.removeClass('disabled');
611            el.unbind('click.w2pDisable');
612        },
613        /*convenience wrapper, internal use only */
614        simple_component: function (action, target, element) {
615            web2py.component(action, target, 0, 1, element);
616        },
617        /*helper for flash messages*/
618        flash: function (message, status) {
619            var flash = $('.w2p_flash');
620            web2py.hide_flash();
621            flash.text(message).addClass(status);
622            if (flash.html()) flash.append('<span id="closeflash"> &times; </span>')[animateIn]();
623        },
624        hide_flash: function () {
625            $('.w2p_flash').fadeOut(0).html('');
626        },
627        show_if_handler: function (target) {
628            var triggers = {};
629            var show_if = function () {
630                var t = $(this);
631                var id = t.attr('id');
632                t.attr('value', t.val());
633                for (var k = 0; k < triggers[id].length; k++) {
634                    var dep = $('#' + triggers[id][k], target);
635                    var tr = $('#' + triggers[id][k] + '__row', target);
636                    if (t.is(dep.attr('data-show-if'))) tr[animateIn]();
637                    else tr.hide();
638                }
639            };
640            $('[data-show-trigger]', target).each(function () {
641                var name = $(this).attr('data-show-trigger');
642                // The field exists only when creating/editing a row
643                if ($('#' + name).length) {
644                    if (!triggers[name]) triggers[name] = [];
645                    triggers[name].push($(this).attr('id'));
646                }
647            });
648            for (var name in triggers) {
649                $('#' + name, target).change(show_if).keyup(show_if);
650                show_if.call($('#' + name, target));
651            }
652        },
653        component_handler: function (target) {
654            $('div[data-w2p_remote]', target).each(function () {
655                var remote, times, timeout, target;
656                var el = $(this);
657                remote = el.data('w2p_remote');
658                times = el.data('w2p_times');
659                timeout = el.data('w2p_timeout');
660                target = el.attr('id');
661                web2py.component(remote, target, timeout, times, $(this));
662            });
663        },
664        a_handler: function (el, e) {
665            e.preventDefault();
666            var method = el.data('w2p_method');
667            var action = el.attr('href');
668            var target = el.data('w2p_target');
669            var confirm_message = el.data('w2p_confirm');
670
671            var pre_call = el.data('w2p_pre_call');
672            if (!web2py.isUndefined(pre_call)) {
673                eval(pre_call);
674            }
675            if (confirm_message) {
676                if (confirm_message == 'default') {
677                    confirm_message = !web2py.isUndefined(w2p_ajax_confirm_message) ? 
678                    w2p_ajax_confirm_message : 'Are you sure you want to delete this object?';
679                }
680                if (!web2py.confirm(confirm_message)) {
681                    web2py.stopEverything(e);
682                    return;
683                }
684            }
685            if (web2py.isUndefined(target)) {
686                if (method == 'GET') {
687                    web2py.ajax_page('get', action, [], '', el);
688                } else if (method == 'POST') {
689                    web2py.ajax_page('post', action, [], '', el);
690                }
691            } else {
692                if (method == 'GET') {
693                    web2py.ajax_page('get', action, [], target, el);
694                } else if (method == 'POST') {
695                    web2py.ajax_page('post', action, [], target, el);
696                }
697            }
698        },
699        a_handlers: function () {
700            var el = $(document);
701            el.on('click', 'a[data-w2p_method]', function (e) {
702                web2py.a_handler($(this), e);
703            });
704            /* removal of element should happen only on success */
705            el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function () {
706                var el = $(this);
707                var toremove = el.data('w2p_remove');
708                if (!web2py.isUndefined(toremove)) {
709                    toremove = el.closest(toremove);
710                    if (!toremove.length) {
711                        /*this enables removal of whatever selector if a closest is not found */
712                        toremove = $(toremove);
713                    }
714                    toremove.remove();
715                }
716            });
717            el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function () {
718                web2py.disableElement($(this));
719            });
720            /*re-enable click on completion*/
721            el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function () {
722                web2py.enableElement($(this));
723            });
724        },
725        /* Disables form elements:
726        - Does not disable elements with 'data-w2p_disable' attribute
727        - Caches element value in 'w2p_enable_with' data store
728        - Replaces element text with value of 'data-w2p_disable_with' attribute
729        - Sets disabled property to true
730        */
731        disableFormElements: function (form) {
732            form.find(web2py.disableSelector).each(function () {
733                var element = $(this),
734                    method = element.is('button') ? 'html' : 'val';
735                var disable_with = element.data('w2p_disable_with');
736                var disable = element.data('w2p_disable');
737                if (!web2py.isUndefined(disable)) {
738                    return false;
739                }
740                if (!element.is(':file')) { // Altering file input values is not allowed.
741                    if (web2py.isUndefined(disable_with)) {
742                        element.data('w2p_disable_with', element[method]());
743                    }
744                    if (web2py.isUndefined(element.data('w2p_enable_with'))) {
745                        element.data('w2p_enable_with', element[method]());
746                    }
747                    element[method](element.data('w2p_disable_with'));
748                }
749                element.prop('disabled', true);
750            });
751        },
752
753        /* Re-enables disabled form elements:
754        - Replaces element text with cached value from 'w2p_enable_with' data store (created in `disableFormElements`)
755        - Sets disabled property to false
756        */
757        enableFormElements: function (form) {
758            form.find(web2py.enableSelector).each(function () {
759                var element = $(this),
760                    method = element.is('button') ? 'html' : 'val';
761                if (element.data('w2p_enable_with')) {
762                    element[method](element.data('w2p_enable_with'));
763                    element.removeData('w2p_enable_with');
764                }
765                element.prop('disabled', false);
766            });
767        },
768        form_handlers: function () {
769            var el = $(document);
770            el.on('ajax:beforeSend', 'form[data-w2p_target]', function () {
771                web2py.disableFormElements($(this));
772            });
773            el.on('ajax:complete', 'form[data-w2p_target]', function () {
774                web2py.enableFormElements($(this));
775            });
776        },
777        /* Invalidate and force reload of a web2py component
778         */
779        invalidate: function (target) {
780            $('div[data-w2p_remote]', target).each(function () {
781                var el = $('#' + $(this).attr('id')).get(0);
782                if (!web2py.isUndefined(el.timing)) { // Block triggering regular routines
783                    clearInterval(el.timing);
784                }
785            });
786            $.web2py.component_handler(target);
787        },
788        main_hook: function () {
789            var flash = $('.w2p_flash');
790            flash.hide();
791            if (flash.html()) web2py.flash(flash.html());
792            web2py.ajax_init(document);
793            web2py.event_handlers();
794            web2py.a_handlers();
795            web2py.form_handlers();
796        }
797    };
798    /*end of functions */
799    /*main hook*/
800    $(function () {
801        web2py.main_hook();
802    });
803
804})(jQuery);
805
806/* compatibility code - start */
807ajax = jQuery.web2py.ajax;
808web2py_component = jQuery.web2py.component;
809web2py_websocket = jQuery.web2py.web2py_websocket;
810web2py_ajax_page = jQuery.web2py.ajax_page;
811/*needed for IS_STRONG(entropy)*/
812web2py_validate_entropy = jQuery.web2py.validate_entropy;
813/*needed for crud.search and SQLFORM.grid's search*/
814web2py_ajax_fields = jQuery.web2py.ajax_fields;
815/*used for LOAD(ajax=False)*/
816web2py_trap_form = jQuery.web2py.trap_form;
817
818/*undocumented - rare*/
819popup = jQuery.web2py.popup;
820collapse = jQuery.web2py.collapse;
821fade = jQuery.web2py.fade;
822
823/* internals - shouldn't be needed
824web2py_ajax_init = jQuery.web2py.ajax_init;
825web2py_event_handlers = jQuery.web2py.event_handlers;
826web2py_trap_link = jQuery.web2py.trap_link;
827web2py_calc_entropy = jQuery.web2py.calc_entropy;
828*/
829/* compatibility code - end*/
Note: See TracBrowser for help on using the repository browser.