PageSourceSearch

https://xn--b1abdmprgchuq.xn--p1ai/assets/framework.js

js xn--b1abdmprgchuq.xn--p1ai collected 2026-10-06 06:38:53 UTC 18,858 bytes, 495 lines download raw bytes

1/* ========================================================================
2 * OctoberCMS: front-end JavaScript framework
3 * http://octobercms.com
4 * ========================================================================
5 * Copyright 2017 Alexey Bobkov, Samuel Georges
6 * ======================================================================== */
7
8if (window.jQuery === undefined) {
9    throw new Error('The jQuery library is not loaded. The OctoberCMS framework cannot be initialized.');
10}
11if (window.jQuery.request !== undefined) {
12    throw new Error('The OctoberCMS framework is already loaded.');
13}
14
15+function ($) { "use strict";
16
17    var Request = function (element, handler, options) {
18        var $el = this.$el = $(element);
19        this.options = options || {};
20
21        /*
22         * Validate handler name
23         */
24        if (handler === undefined) {
25            throw new Error('The request handler name is not specified.')
26        }
27
28        if (!handler.match(/^(?:\w+\:{2})?on*/)) {
29            throw new Error('Invalid handler name. The correct handler name format is: "onEvent".')
30        }
31
32        /*
33         * Prepare the options and execute the request
34         */
35        var $form = options.form ? $(options.form) : $el.closest('form'),
36            $triggerEl = !!$form.length ? $form : $el,
37            context = { handler: handler, options: options }
38
39        $el.trigger('ajaxSetup', [context])
40        var _event = jQuery.Event('oc.beforeRequest')
41        $triggerEl.trigger(_event, context)
42        if (_event.isDefaultPrevented()) return
43
44        var data = [$form.serialize()],
45            loading = options.loading !== undefined ? options.loading : null,
46            isRedirect = options.redirect !== undefined && options.redirect.length,
47            useFlash = options.flash !== undefined
48
49        $.each($el.parents('[data-request-data]').toArray().reverse(), function extendRequest() {
50            data.push($.param(paramToObj('data-request-data', $(this).data('request-data'))))
51        })
52
53        if ($el.is(':input') && !$form.length) {
54            var inputName = $el.attr('name')
55            if (inputName !== undefined && options.data[inputName] === undefined)
56                options.data[inputName] = $el.val()
57        }
58
59        if (options.data !== undefined && !$.isEmptyObject(options.data)) {
60            data.push($.param(options.data))
61        }
62
63        if ($.type(loading) == 'string') {
64            loading = $(loading)
65        }
66
67        var requestHeaders = {
68            'X-OCTOBER-REQUEST-HANDLER': handler,
69            'X-OCTOBER-REQUEST-PARTIALS': this.extractPartials(options.update)
70        }
71
72        if (useFlash) {
73            requestHeaders['X-OCTOBER-REQUEST-FLASH'] = 1
74        }
75
76        var requestOptions = {
77            url: window.location.href,
78            crossDomain: false,
79            context: context,
80            headers: requestHeaders,
81            success: function(data, textStatus, jqXHR) {
82                /*
83                 * Halt here if beforeUpdate() or data-request-before-update returns false
84                 */
85                if (this.options.beforeUpdate.apply(this, [data, textStatus, jqXHR]) === false) return
86                if (options.evalBeforeUpdate && eval('(function($el, context, data, textStatus, jqXHR) {'+options.evalBeforeUpdate+'}.call($el.get(0), $el, context, data, textStatus, jqXHR))') === false) return
87
88                /*
89                 * Trigger 'ajaxBeforeUpdate' on the form, halt if event.preventDefault() is called
90                 */
91                var _event = jQuery.Event('ajaxBeforeUpdate')
92                $triggerEl.trigger(_event, [context, data, textStatus, jqXHR])
93                if (_event.isDefaultPrevented()) return
94
95                if (useFlash && data['X_OCTOBER_FLASH_MESSAGES']) {
96                    $.each(data['X_OCTOBER_FLASH_MESSAGES'], function(type, message) {
97                        requestOptions.handleFlashMessage(message, type)
98                    })
99                }
100
101                /*
102                 * Proceed with the update process
103                 */
104                var updatePromise = requestOptions.handleUpdateResponse(data, textStatus, jqXHR)
105
106                updatePromise.done(function() {
107                    $triggerEl.trigger('ajaxSuccess', [context, data, textStatus, jqXHR])
108                    options.evalSuccess && eval('(function($el, context, data, textStatus, jqXHR) {'+options.evalSuccess+'}.call($el.get(0), $el, context, data, textStatus, jqXHR))')
109                })
110
111                return updatePromise
112            },
113            error: function(jqXHR, textStatus, errorThrown) {
114                var errorMsg,
115                    updatePromise = $.Deferred()
116
117                if ((window.ocUnloading !== undefined && window.ocUnloading) || errorThrown == 'abort')
118                    return
119
120                /*
121                 * Disable redirects
122                 */
123                isRedirect = false
124                options.redirect = null
125
126                /*
127                 * Error 406 is a "smart error" that returns response object that is
128                 * processed in the same fashion as a successful response.
129                 */
130                if (jqXHR.status == 406 && jqXHR.responseJSON) {
131                    errorMsg = jqXHR.responseJSON['X_OCTOBER_ERROR_MESSAGE']
132                    updatePromise = requestOptions.handleUpdateResponse(jqXHR.responseJSON, textStatus, jqXHR)
133                }
134                /*
135                 * Standard error with standard response text
136                 */
137                else {
138                    errorMsg = jqXHR.responseText ? jqXHR.responseText : jqXHR.statusText
139                    updatePromise.resolve()
140                }
141
142                updatePromise.done(function() {
143                    $el.data('error-message', errorMsg)
144
145                    /*
146                     * Trigger 'ajaxError' on the form, halt if event.preventDefault() is called
147                     */
148                    var _event = jQuery.Event('ajaxError')
149                    $triggerEl.trigger(_event, [context, errorMsg, textStatus, jqXHR])
150                    if (_event.isDefaultPrevented()) return
151
152                    /*
153                     * Halt here if the data-request-error attribute returns false
154                     */
155                    if (options.evalError && eval('(function($el, context, errorMsg, textStatus, jqXHR) {'+options.evalError+'}.call($el.get(0), $el, context, errorMsg, textStatus, jqXHR))') === false)
156                        return
157
158                    requestOptions.handleErrorMessage(errorMsg)
159                })
160
161                return updatePromise
162            },
163            complete: function(data, textStatus, jqXHR) {
164                $triggerEl.trigger('ajaxComplete', [context, data, textStatus, jqXHR])
165                options.evalComplete && eval('(function($el, context, data, textStatus, jqXHR) {'+options.evalComplete+'}.call($el.get(0), $el, context, data, textStatus, jqXHR))')
166            },
167
168            /*
169             * Custom function, requests confirmation from the user
170             */
171            handleConfirmMessage: function(message) {
172                var _event = jQuery.Event('ajaxConfirmMessage')
173
174                _event.promise = $.Deferred()
175                if ($(window).triggerHandler(_event, [message]) !== undefined) {
176                    _event.promise.done(function() {
177                        options.confirm = null
178                        new Request(element, handler, options)
179                    })
180                    return false
181                }
182
183                if (_event.isDefaultPrevented()) return
184                if (message) return confirm(message)
185            },
186
187            /*
188             * Custom function, display an error message to the user
189             */
190            handleErrorMessage: function(message) {
191                var _event = jQuery.Event('ajaxErrorMessage')
192                $(window).trigger(_event, [message])
193                if (_event.isDefaultPrevented()) return
194                if (message) alert(message)
195            },
196
197            /*
198             * Custom function, focus fields with errors
199             */
200            handleValidationMessage: function(message, fields) {
201                $triggerEl.trigger('ajaxValidation', [context, message, fields])
202
203                var isFirstInvalidField = true
204                $.each(fields, function focusErrorField(fieldName, fieldMessages) {
205                    var fieldElement = $form.find('[name="'+fieldName+'"], [name="'+fieldName+'[]"], [name$="['+fieldName+']"], [name$="['+fieldName+'][]"]').filter(':enabled').first()
206                    if (fieldElement.length > 0) {
207
208                        var _event = jQuery.Event('ajaxInvalidField')
209                        $(window).trigger(_event, [fieldElement.get(0), fieldName, fieldMessages, isFirstInvalidField])
210
211                        if (isFirstInvalidField) {
212                            if (!_event.isDefaultPrevented()) fieldElement.focus()
213                            isFirstInvalidField = false
214                        }
215                    }
216                })
217            },
218
219            /*
220             * Custom function, display a flash message to the user
221             */
222            handleFlashMessage: function(message, type) {},
223
224            /*
225             * Custom function, redirect the browser to another location
226             */
227            handleRedirectResponse: function(url) {
228                window.location.href = url
229            },
230
231            /*
232             * Custom function, handle any application specific response values
233             * Using a promisary object here in case injected assets need time to load
234             */
235            handleUpdateResponse: function(data, textStatus, jqXHR) {
236
237                /*
238                 * Update partials and finish request
239                 */
240                var updatePromise = $.Deferred().done(function() {
241                    for (var partial in data) {
242                        /*
243                         * If a partial has been supplied on the client side that matches the server supplied key, look up
244                         * it's selector and use that. If not, we assume it is an explicit selector reference.
245                         */
246                        var selector = (options.update[partial]) ? options.update[partial] : partial
247                        if ($.type(selector) == 'string' && selector.charAt(0) == '@') {
248                            $(selector.substring(1)).append(data[partial]).trigger('ajaxUpdate', [context, data, textStatus, jqXHR])
249                        }
250                        else if ($.type(selector) == 'string' && selector.charAt(0) == '^') {
251                            $(selector.substring(1)).prepend(data[partial]).trigger('ajaxUpdate', [context, data, textStatus, jqXHR])
252                        }
253                        else {
254                            $(selector).trigger('ajaxBeforeReplace')
255                            $(selector).html(data[partial]).trigger('ajaxUpdate', [context, data, textStatus, jqXHR])
256                        }
257                    }
258
259                    /*
260                     * Wait for .html() method to finish rendering from partial updates
261                     */
262                    setTimeout(function() {
263                        $(window)
264                            .trigger('ajaxUpdateComplete', [context, data, textStatus, jqXHR])
265                            .trigger('resize')
266                    }, 0)
267                })
268
269                /*
270                 * Handle redirect
271                 */
272                if (data['X_OCTOBER_REDIRECT']) {
273                    options.redirect = data['X_OCTOBER_REDIRECT']
274                    isRedirect = true
275                }
276
277                if (isRedirect) {
278                    requestOptions.handleRedirectResponse(options.redirect)
279                }
280
281                /*
282                 * Handle validation
283                 */
284                if (data['X_OCTOBER_ERROR_FIELDS']) {
285                    requestOptions.handleValidationMessage(data['X_OCTOBER_ERROR_MESSAGE'], data['X_OCTOBER_ERROR_FIELDS'])
286                }
287
288                /*
289                 * Handle asset injection
290                 */
291                 if (data['X_OCTOBER_ASSETS']) {
292                    assetManager.load(data['X_OCTOBER_ASSETS'], $.proxy(updatePromise.resolve, updatePromise))
293                 }
294                 else {
295                    updatePromise.resolve()
296                }
297
298                return updatePromise
299            }
300        }
301
302        /*
303         * Allow default business logic to be called from user functions
304         */
305        context.success = requestOptions.success
306        context.error = requestOptions.error
307        context.complete = requestOptions.complete
308        requestOptions = $.extend(requestOptions, options)
309        requestOptions.data = data.join('&')
310
311        /*
312         * Initiate request
313         */
314        if (options.confirm && !requestOptions.handleConfirmMessage(options.confirm)) {
315            return
316        }
317
318        if (loading) loading.show()
319        $(window).trigger('ajaxBeforeSend', [context])
320        $el.trigger('ajaxPromise', [context])
321
322        return $.ajax(requestOptions)
323            .fail(function(jqXHR, textStatus, errorThrown) {
324                if (!isRedirect) {
325                    $el.trigger('ajaxFail', [context, textStatus, jqXHR])
326                    if (loading) loading.hide()
327                }
328            })
329            .done(function(data, textStatus, jqXHR) {
330                if (!isRedirect) {
331                    $el.trigger('ajaxDone', [context, data, textStatus, jqXHR])
332                    if (loading) loading.hide()
333                }
334            })
335            .always(function(dataOrXhr, textStatus, xhrOrError) {
336                $el.trigger('ajaxAlways', [context, dataOrXhr, textStatus, xhrOrError])
337            })
338    }
339
340    Request.DEFAULTS = {
341        update: {},
342        type : 'POST',
343        beforeUpdate: function(data, textStatus, jqXHR) {},
344        evalBeforeUpdate: null,
345        evalSuccess: null,
346        evalError: null,
347        evalComplete: null,
348    }
349
350    /*
351     * Internal function, build a string of partials and their update elements.
352     */
353    Request.prototype.extractPartials = function(update) {
354        var result = []
355
356        for (var partial in update)
357            result.push(partial)
358
359        return result.join('&')
360    }
361
362    // REQUEST PLUGIN DEFINITION
363    // ============================
364
365    var old = $.fn.request
366
367    $.fn.request = function(handler, option) {
368        var args = arguments
369
370        var $this = $(this).first()
371        var data  = {
372            evalBeforeUpdate: $this.data('request-before-update'),
373            evalSuccess: $this.data('request-success'),
374            evalError: $this.data('request-error'),
375            evalComplete: $this.data('request-complete'),
376            confirm: $this.data('request-confirm'),
377            redirect: $this.data('request-redirect'),
378            loading: $this.data('request-loading'),
379            flash: $this.data('request-flash'),
380            form: $this.data('request-form'),
381            update: paramToObj('data-request-update', $this.data('request-update')),
382            data: paramToObj('data-request-data', $this.data('request-data'))
383        }
384        if (!handler) handler = $this.data('request')
385        var options = $.extend(true, {}, Request.DEFAULTS, data, typeof option == 'object' && option)
386        return new Request($this, handler, options)
387    }
388
389    $.fn.request.Constructor = Request
390
391    $.request = function(handler, option) {
392        return $(document).request(handler, option)
393    }
394
395    // REQUEST NO CONFLICT
396    // =================
397
398    $.fn.request.noConflict = function() {
399        $.fn.request = old
400        return this
401    }
402
403    // REQUEST DATA-API
404    // ==============
405
406    function paramToObj(name, value) {
407        if (value === undefined) value = ''
408        if (typeof value == 'object') return value
409
410        try {
411            return JSON.parse(JSON.stringify(eval("({" + value + "})")))
412        }
413        catch (e) {
414            throw new Error('Error parsing the '+name+' attribute value. '+e)
415        }
416    }
417
418    $(document).on('change', 'select[data-request], input[type=radio][data-request], input[type=checkbox][data-request]', function documentOnChange() {
419        $(this).request()
420    })
421
422    $(document).on('click', 'a[data-request], button[data-request], input[type=button][data-request], input[type=submit][data-request]', function documentOnClick(e) {
423        e.preventDefault()
424
425        $(this).request()
426
427        if ($(this).is('[type=submit]'))
428            return false
429    })
430
431    $(document).on('keydown', 'input[type=text][data-request], input[type=submit][data-request], input[type=password][data-request]', function documentOnKeydown(e) {
432        if (e.keyCode == 13) {
433            if (this.dataTrackInputTimer !== undefined)
434                window.clearTimeout(this.dataTrackInputTimer)
435
436            $(this).request()
437            return false
438        }
439    })
440
441    $(document).on('keyup', 'input[data-request][data-track-input]', function documentOnKeyup(e) {
442        var
443            $el = $(this),
444            lastValue = $el.data('oc.lastvalue')
445
446        if (!$el.is('[type=email],[type=number],[type=password],[type=search],[type=text]'))
447            return
448
449        if (lastValue !== undefined && lastValue == this.value)
450            return
451
452        $el.data('oc.lastvalue', this.value)
453
454        if (this.dataTrackInputTimer !== undefined)
455            window.clearTimeout(this.dataTrackInputTimer)
456
457        var interval = $(this).data('track-input')
458        if (!interval)
459            interval = 300
460
461        var self = this
462        this.dataTrackInputTimer = window.setTimeout(function() {
463            $(self).request()
464        }, interval)
465    })
466
467    $(document).on('submit', '[data-request]', function documentOnSubmit() {
468        $(this).request()
469        return false
470    })
471
472    $(window).on('beforeunload', function documentOnBeforeUnload() {
473        window.ocUnloading = true
474    })
475
476    /*
477     * Invent our own event that unifies document.ready with window.ajaxUpdateComplete
478     *
479     * $(document).render(function() { })
480     * $(document).on('render', function() { })
481     */
482
483    $(document).ready(function triggerRenderOnReady() {
484        $(document).trigger('render')
485    })
486
487    $(window).on('ajaxUpdateComplete', function triggerRenderOnAjaxUpdateComplete() {
488        $(document).trigger('render')
489    })
490
491    $.fn.render = function(callback) {
492        $(document).on('render', callback)
493    }
494
495}(window.jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.