PageSourceSearch

https://itaipue.org.mx/soporte/js/redactor-osticket.js?9ae093d

js itaipue.org.mx collected 2026-10-06 12:52:36 UTC 15,696 bytes, 380 lines download raw bytes

1if (typeof RedactorPlugins === 'undefined') var RedactorPlugins = {};
2
3/* Generic draft support for osTicket. The plugins supports draft retrieval
4 * automatically, along with draft autosave, and image uploading.
5 *
6 * Configuration:
7 * draftNamespace: namespace for the draft retrieval
8 * draftObjectId: extension to the namespace for draft retrieval
9 *
10 * Caveats:
11 * Login (staff only currently) is required server-side for drafts and image
12 * uploads. Furthermore, the id of the staff is considered for the drafts,
13 * so one user will not retrieve drafts for another user.
14 */
15RedactorPlugins.draft = function() {
16  return {
17    init: function() {
18        if (!this.opts.draftNamespace)
19            return;
20
21        this.opts.changeCallback = this.draft.hideDraftSaved;
22        var autosave_url = 'ajax.php/draft/' + this.opts.draftNamespace;
23        if (this.opts.draftObjectId)
24            autosave_url += '.' + this.opts.draftObjectId;
25        this.opts.autosave = this.opts.autoCreateUrl = autosave_url;
26        this.opts.autosaveInterval = 30;
27        this.opts.autosaveCallback = this.draft.afterUpdateDraft;
28        this.opts.autosaveErrorCallback = this.draft.autosaveFailed;
29        this.opts.imageUploadErrorCallback = this.draft.displayError;
30        if (this.opts.draftId) {
31            this.opts.autosave = 'ajax.php/draft/'+this.opts.draftId;
32            this.opts.clipboardUploadUrl =
33            this.opts.imageUpload =
34                'ajax.php/draft/'+this.opts.draftId+'/attach';
35        }
36        else if (this.$textarea.hasClass('draft')) {
37            // Just upload the file. A draft will be created automatically
38            // and will be configured locally in the afterUpateDraft()
39            this.opts.clipboardUploadUrl =
40            this.opts.imageUpload = this.opts.autoCreateUrl + '/attach';
41            this.opts.imageUploadCallback = this.afterUpdateDraft;
42        }
43
44        // FIXME: Monkey patch Redactor's autosave enable method to disable first
45        var oldAse = this.autosave.enable;
46        this.autosave.enable = function() {
47            this.autosave.disable();
48            oldAse.call(this);
49        }.bind(this);
50
51        if (autosave_url)
52            this.autosave.enable();
53
54        if (this.$textarea.hasClass('draft')) {
55            this.$draft_saved = $('<span>')
56                .addClass("pull-right draft-saved")
57                .hide()
58                .append($('<span>')
59                    .text(__('Draft Saved')));
60            // Float the [Draft Saved] box with the toolbar
61            this.$toolbar.append(this.$draft_saved);
62
63            // Add [Delete Draft] button to the toolbar
64            if (this.opts.draftDelete) {
65                var trash = this.draft.deleteButton =
66                    this.button.add('deleteDraft', __('Delete Draft'))
67                this.button.addCallback(trash, this.draft.deleteDraft);
68                this.button.setAwesome('deleteDraft', 'icon-trash');
69                trash.parent().addClass('pull-right');
70                trash.addClass('delete-draft');
71                if (!this.opts.draftId)
72                    trash.hide();
73            }
74        }
75        if (this.code.get())
76            this.$box.trigger('draft:recovered');
77    },
78    afterUpdateDraft: function(name, data) {
79        // If the draft was created, a draft_id will be sent back — update
80        // the URL to send updates in the future
81        if (!this.opts.draftId && data.draft_id) {
82            this.opts.draftId = data.draft_id;
83            this.opts.autosave = 'ajax.php/draft/' + data.draft_id;
84            this.opts.clipboardUploadUrl =
85            this.opts.imageUpload =
86                'ajax.php/draft/'+this.opts.draftId+'/attach';
87            if (!this.code.get())
88                this.code.set(' ', false);
89        }
90        // Only show the [Draft Saved] notice if there is content in the
91        // field that has been touched
92        if (!this.draft.firstSave) {
93            this.draft.firstSave = true;
94            // No change yet — dont't show the button
95            return;
96        }
97        if (data && this.code.get()) {
98            this.$draft_saved.show().delay(5000).fadeOut();
99        }
100        // Show the button if there is a draft to delete
101        if (this.opts.draftId && this.opts.draftDelete)
102            this.draft.deleteButton.show();
103        this.$box.trigger('draft:saved');
104    },
105    autosaveFailed: function(error) {
106        if (error.code == 422)
107            // Unprocessable request (Empty message)
108            return;
109
110        this.draft.displayError(error);
111        // Cancel autosave
112        this.autosave.disable();
113        this.hideDraftSaved();
114        this.$box.trigger('draft:failed');
115    },
116
117    displayError: function(json) {
118        $.sysAlert(json.error,
119            __('Unable to save draft.')
120          + __('Refresh the current page to restore and continue your draft.'));
121    },
122
123    hideDraftSaved: function() {
124        this.$draft_saved.hide();
125    },
126
127    deleteDraft: function() {
128        if (!this.opts.draftId)
129            // Nothing to delete
130            return;
131        var self = this;
132        $.ajax('ajax.php/draft/'+this.opts.draftId, {
133            type: 'delete',
134            async: false,
135            success: function() {
136                self.draft_id = self.opts.draftId = undefined;
137                self.draft.hideDraftSaved();
138                self.code.set(self.opts.draftOriginal || '', false, false);
139                self.opts.autosave = self.opts.autoCreateUrl;
140                self.draft.deleteButton.hide();
141                self.draft.firstSave = false;
142                self.$box.trigger('draft:deleted');
143            }
144        });
145    }
146  };
147};
148
149RedactorPlugins.autolock = function() {
150  return {
151    init: function() {
152      var code = this.$box.closest('form').find('[name=lockCode]'),
153          self = this;
154      if (code.length)
155        this.opts.keydownCallback = function(e) {
156          self.$box.closest('[data-lock-object-id]').exclusive('acquire');
157        };
158    }
159  };
160}
161
162RedactorPlugins.signature = function() {
163  return {
164    init: function() {
165        var $el = $(this.$element.get(0)),
166            inner = $('<div class="inner"></div>');
167        if ($el.data('signatureField')) {
168            this.$signatureBox = $('<div class="selected-signature"></div>')
169                .append(inner)
170                .appendTo(this.$box);
171            if ($el.data('signature'))
172                inner.html($el.data('signature'));
173            else
174                this.$signatureBox.hide();
175            $('input[name='+$el.data('signatureField')+']', $el.closest('form'))
176                .on('change', false, false, $.proxy(this.signature.updateSignature, this));
177            if ($el.data('deptField'))
178                $(':input[name='+$el.data('deptField')+']', $el.closest('form'))
179                    .on('change', false, false, $.proxy(this.signature.updateSignature, this));
180            // Expand on hover
181            var outer = this.$signatureBox,
182                inner = $('.inner', this.$signatureBox).get(0),
183                originalHeight = outer.height(),
184                hoverTimeout = undefined,
185                originalShadow = this.$signatureBox.css('box-shadow');
186            this.$signatureBox.hover(function() {
187                hoverTimeout = setTimeout($.proxy(function() {
188                    originalHeight = Math.max(originalHeight, outer.height());
189                    $(this).animate({
190                        'height': inner.offsetHeight
191                    }, 'fast');
192                    $(this).css('box-shadow', 'none', 'important');
193                }, this), 250);
194            }, function() {
195                clearTimeout(hoverTimeout);
196                $(this).stop().animate({
197                    'height': Math.min(inner.offsetHeight, originalHeight)
198                }, 'fast');
199                $(this).css('box-shadow', originalShadow);
200            });
201            this.$box.find('.redactor_editor').css('border-bottom-style', 'none', true);
202        }
203    },
204    updateSignature: function(e) {
205        var $el = $(this.$element.get(0));
206            selected = $(':input:checked[name='+$el.data('signatureField')+']', $el.closest('form')).val(),
207            type = $(e.target).val(),
208            dept = $(':input[name='+$el.data('deptField')+']', $el.closest('form')).val(),
209            url = 'ajax.php/content/signature/',
210            inner = $('.inner', this.$signatureBox);
211        e.preventDefault && e.preventDefault();
212        if (selected == 'dept' && $el.data('deptId'))
213            url += 'dept/' + $el.data('deptId');
214        else if (selected == 'dept' && $el.data('deptField')) {
215            if (dept)
216                url += 'dept/' + dept;
217            else
218                return inner.empty().parent().hide();
219        }
220        else if (selected == 'theirs' && $el.data('posterId')) {
221            url += 'agent/' + $el.data('posterId');
222        }
223        else if (type == 'none')
224           return inner.empty().parent().hide();
225        else
226            url += selected;
227
228        inner.load(url).parent().show();
229    }
230  }
231};
232
233/* Redactor richtext init */
234$(function() {
235    var captureImageSizes = function(html) {
236        $('img', this.$box).each(function(i, img) {
237            // TODO: Rewrite the entire <img> tag. Otherwise the @width
238            // and @height attributes will begin to accumulate
239            before = img.outerHTML;
240            if (img.clientWidth && img.clientHeight)
241                $(img).attr('width', img.clientWidth)
242                      .attr('height',img.clientHeight);
243            html = html.replace(before, img.outerHTML);
244        });
245        return html;
246    },
247    redact = $.redact = function(el, options) {
248        var el = $(el),
249            sizes = {'small': 75, 'medium': 150, 'large': 225},
250            selectedSize = sizes['medium'];
251        $.each(sizes, function(k, v) {
252            if (el.hasClass(k)) selectedSize = v;
253        });
254        var options = $.extend({
255                'air': el.hasClass('no-bar'),
256                'buttons': el.hasClass('no-bar')
257                  ? ['formatting', '|', 'bold', 'italic', 'underline', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'link', 'image']
258                  : ['html', '|', 'formatting', '|', 'bold',
259                    'italic', 'underline', 'deleted', '|', 'unorderedlist',
260                    'orderedlist', 'outdent', 'indent', '|', 'image', 'video',
261                    'file', 'table', 'link', '|', 'alignment', '|',
262                    'horizontalrule'],
263                'buttonSource': !el.hasClass('no-bar'),
264                'autoresize': !el.hasClass('no-bar') && !el.closest('.dialog').length,
265                'maxHeight': el.closest('.dialog').length ? selectedSize : false,
266                'minHeight': selectedSize,
267                'focus': false,
268                'plugins': el.hasClass('no-bar')
269                  ? ['imagemanager','definedlinks']
270                  : ['imagemanager','imageannotate','table','video','definedlinks','autolock'],
271                'imageUpload': el.hasClass('draft'),
272                'imageManagerJson': 'ajax.php/draft/images/browse',
273                'syncBeforeCallback': captureImageSizes,
274                'linebreaks': true,
275                'tabFocus': false,
276                'toolbarFixedBox': true,
277                'focusCallback': function() { this.$box.addClass('no-pjax'); },
278                'initCallback': function() {
279                    if (this.$element.data('width'))
280                        this.$editor.width(this.$element.data('width'));
281                    this.$editor.attr('spellcheck', 'true');
282                    var lang = this.$editor.closest('[lang]').attr('lang');
283                    if (lang)
284                        this.$editor.attr('lang', lang);
285                },
286                'linkSize': 100000,
287                'definedLinks': 'ajax.php/config/links'
288            }, options||{});
289        if (el.data('redactor')) return;
290        var reset = $('input[type=reset]', el.closest('form'));
291        if (reset) {
292            reset.click(function() {
293                if (el.hasClass('draft'))
294                    el.redactor('deleteDraft');
295                else
296                    el.redactor('set', '', false, false);
297            });
298        }
299        $('input[type=submit]', el.closest('form')).on('click', function() {
300            // Some setups (IE v10 on Windows 7 at least) seem to have a bug
301            // where Redactor does not sync properly after adding an image.
302            // Therefore, the ::get() call will not include text added after
303            // the image was inserted.
304            el.redactor('code.sync');
305        });
306        if (!$.clientPortal) {
307            options['plugins'] = options['plugins'].concat(
308                    'fontcolor', 'fontfamily', 'signature');
309        }
310        if (el.hasClass('draft')) {
311            el.closest('form').append($('<input type="hidden" name="draft_id"/>'));
312            options['plugins'].push('draft');
313            options['plugins'].push('imagepaste');
314            options.draftDelete = el.hasClass('draft-delete');
315        }
316        if (true || 'scp') { // XXX: Add this to SCP only
317            options['plugins'].push('contexttypeahead');
318        }
319        if (el.hasClass('fullscreen'))
320            options['plugins'].push('fullscreen');
321        if (el.data('translateTag'))
322            options['plugins'].push('translatable');
323        if ($('#thread-items[data-thread-id]').length)
324            options['imageManagerJson'] += '?threadId=' + $('#thread-items').data('threadId');
325        getConfig().then(function(c) {
326            if (c.lang && c.lang.toLowerCase() != 'en_us' &&
327                    $.Redactor.opts.langs[c.short_lang])
328                options['lang'] = c.short_lang;
329            //if (c.has_rtl)
330              //  options['plugins'].push('textdirection');
331            if (el.find('rtl').length)
332                options['direction'] = 'rtl';
333            el.redactor(options);
334        });
335    },
336    findRichtextBoxes = function() {
337        $('.richtext').each(function(i,el) {
338            if ($(el).hasClass('ifhtml'))
339                // Check if html_thread is enabled first
340                getConfig().then(function(c) {
341                    if (c.html_thread)
342                        redact(el);
343                });
344            else
345                // Make a rich text editor immediately
346                redact(el);
347        });
348    },
349    cleanupRedactorElements = function() {
350        // Tear down redactor editors on this page
351        $('.richtext').each(function() {
352            var redactor = $(this).data('redactor');
353            if (redactor)
354                redactor.core.destroy();
355        });
356    };
357    findRichtextBoxes();
358    $(document).ajaxStop(findRichtextBoxes);
359    $(document).on('pjax:success', findRichtextBoxes);
360    $(document).on('pjax:start', cleanupRedactorElements);
361});
362
363$(document).on('focusout.redactor', 'div.redactor_richtext', function (e) {
364    $(this).siblings('textarea').trigger('change');
365});
366
367$(document).ajaxError(function(event, request, settings) {
368    if (settings.url.indexOf('ajax.php/draft') != -1
369            && settings.type.toUpperCase() == 'POST') {
370        $('.richtext').each(function() {
371            var redactor = $(this).data('redactor');
372            if (redactor) {
373                redactor.autosave.disable();
374                clearInterval(redactor.autosaveInterval);
375            }
376        });
377        $.sysAlert(__('Unable to save draft.'),
378            __('Refresh the current page to restore and continue your draft.'));
379    }
380});

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.