PageSourceSearch

https://stagingabc.org/Resources/libraries/DnnPlugins/10_00_01/dnn.jquery.js?cdv=3798

js stagingabc.org collected 2026-09-29 16:59:06 UTC 175,149 bytes, 4,325 lines download raw bytes

1(function ($) {
2    $.fn.dnnTabs = function (options) {
3        var opts = $.extend({}, $.fn.dnnTabs.defaultOptions, options),
4        $wrap = this;
5
6        // patch for period in selector - http://jsfiddle.net/9Mst9/2/
7        $.ui.tabs.prototype._sanitizeSelector = function (hash) {
8            return hash.replace(/:/g, "\\:").replace(/\./g, "\\\.");
9        };
10
11        $wrap.each(function () {
12            var showEvent, cookieId;
13            if (this.id) {
14                cookieId = 'dnnTabs-' + this.id;
15                if (opts.selected === -1) {
16                    var cookieValue = dnn.dom.getCookie(cookieId);
17                    if (cookieValue) {
18                        opts.selected = cookieValue;
19                    }
20                    if (opts.selected === -1) {
21                        opts.selected = 0;
22                    }
23                }
24                showEvent = (function (cid) {
25                    return function (event, ui) {
26                        dnn.dom.setCookie(cid, ui.newTab.index(), opts.cookieDays, '/', '', false, opts.cookieMilleseconds);
27                    };
28                })(cookieId);
29            } else {
30                showEvent = function () {
31                };
32            }
33
34            $wrap.tabs({
35                activate: showEvent,
36                active: opts.selected,
37                disabled: opts.disabled,
38                fx: {
39                    opacity: opts.opacity,
40                    duration: opts.duration
41                }
42            });
43
44            if (window.location.hash && window.location.hash != '#') {
45                var substr = window.location.hash.substr(0, 50);
46                $('a[href="' + encodeURI(substr) + '"]', $wrap).trigger('click');
47            }
48
49            // page validation integration - select tab that contain tripped validators
50            if (typeof window.Page_ClientValidate != "undefined" && $.isFunction(window.Page_ClientValidate)) {
51                $wrap.find(opts.validationTriggerSelector).click(function () {
52                    if (!window.Page_ClientValidate(opts.validationGroup)) {
53                        var invalidControl = $wrap.find(opts.invalidItemSelector).eq(0);
54                        var $parent = invalidControl.closest(".ui-tabs-panel");
55                        if ($parent.length > 0) {
56                            var tabId = $parent.attr("id");
57                            $parent.parent().find("a[href='#" + tabId + "']").click();
58                        }
59                    }
60                });
61            };
62        });
63
64        return $wrap;
65    };
66
67    $.fn.dnnTabs.defaultOptions = {
68        opacity: 'toggle',
69        duration: 'fast',
70        validationTriggerSelector: '.dnnPrimaryAction',
71        validationGroup: '',
72        invalidItemSelector: '.dnnFormError[style*="inline"]',
73        regionToToggleSelector: 'fieldset',
74        selected: -1,
75        cookieDays: 0,
76        cookieMilleseconds: 1200000 // twenty minutes
77    };
78
79})(jQuery);
80
81(function ($) {
82    $.fn.dnnConfirm = function (options) {
83        var opts = $.extend({}, $.fn.dnnConfirm.defaultOptions, options),
84        $wrap = this;
85        $wrap.each(function () {
86            var $this = $(this),
87                defaultAction = $this.attr('href'),
88                $dnnDialog;
89
90            if (defaultAction || opts.isButton) {
91                $dnnDialog = $("<div class='dnnDialog'></div>").html(opts.text).dialog(opts);
92                $dnnDialog.parent().find('.ui-dialog-titlebar-close').html('Close');
93                $this.click(function (e, isTrigger) {
94                    if (isTrigger) {
95                        return true;
96                    }
97
98                    if ($dnnDialog.is(':visible')) {
99                        $dnnDialog.dialog("close");
100                        return true;
101                    }
102                    $dnnDialog.dialog({
103                        open: function () {
104                            $('.ui-dialog-buttonpane').find('button:contains("' + opts.noText + '")').addClass('dnnConfirmCancel');
105                        },
106                        draggable: false,
107                        buttons: [
108                        {
109                            text: opts.yesText,
110                            click: function () {
111                                $dnnDialog.dialog("close");
112                                if ($.isFunction(opts.callbackTrue)) {
113                                    opts.callbackTrue.call(this);
114                                }
115                                else {
116                                    if (opts.isButton) {
117                                        $this.trigger("click", [true]);
118                                    }
119                                    else {
120                                        window.location.href = defaultAction;
121                                    }
122                                }
123                            },
124                            'class': opts.buttonYesClass
125                        },
126                        {
127                            text: opts.noText,
128                            click: function () {
129                                $(this).dialog("close");
130                                if ($.isFunction(opts.callbackFalse)) {
131                                    opts.callbackFalse.call(this);
132                                };
133                            },
134                            'class': opts.buttonNoClass
135                        }
136                        ]
137                    });
138
139                    $dnnDialog.dialog('open');
140                    e.preventDefault();
141                    return false;
142                });
143            }
144        });
145        return $wrap;
146    };
147
148    $.fn.dnnConfirm.defaultOptions = {
149        text: 'Are you sure?',
150        yesText: 'Yes',
151        noText: 'No',
152        buttonYesClass: 'dnnPrimaryAction',
153        buttonNoClass: 'dnnSecondaryAction',
154        actionUrl: window.location.href,
155        autoOpen: false,
156        resizable: false,
157        modal: true,
158        title: 'Confirm',
159        dialogClass: 'dnnFormPopup dnnClear',
160        isButton: false
161    };
162
163})(jQuery);
164
165(function($) {
166    if ($.dnnConfirm) return;
167
168    $.dnnConfirm = function (opts) {
169        var defaultAction = opts.actionUrl ? opts.actionUrl : 'javascript:void(0);';
170        var shadowLink = $('<a href="' + defaultAction + '" />');
171        shadowLink.dnnConfirm(opts).click();
172    };
173})(jQuery);
174
175(function ($) {
176    $.dnnAlert = function (options) {
177        var opts = $.extend({}, $.dnnAlert.defaultOptions, options),
178        $dnnDialog = $("<div class='dnnDialog'></div>").html(opts.text).dialog(opts);
179
180        $dnnDialog.dialog({
181            buttons: [
182                {
183                    text: opts.okText,
184                    "class": opts.buttonOkClass,
185                    click: function () {
186                        $(this).dialog("close");
187                        if ($.isFunction(opts.callback)) {
188                            opts.callback.call(this);
189                        };
190                        return false;
191                    }
192                }
193            ]
194        });
195        $dnnDialog.dialog('open');
196    };
197
198    $.dnnAlert.defaultOptions = {
199        okText: 'Ok',
200        autoOpen: false,
201        resizable: false,
202        modal: true,
203        buttonOkClass: 'dnnPrimaryAction',
204        dialogClass: 'dnnFormPopup dnnClear'
205    };
206
207})(jQuery);
208
209(function ($) {
210    $.fn.dnnPanels = function (options) {
211        var opts = $.extend({}, $.fn.dnnPanels.defaultOptions, options),
212        $wrap = this;
213
214        $wrap.each(function () {
215            var $this = $(this);
216            if (typeof (opts.onExpand) === "function") {
217                $this.on('onExpand', opts.onExpand);
218            }
219            if (typeof (opts.onHide) === "function") {
220                $this.on('onHide', opts.onHide);
221            }
222            // wire up click event to perform slide toggle
223            $this.find(opts.clickToToggleSelector).click(function (e) {
224                var toggle = $(this).toggleClass(opts.toggleClass).parent().next(opts.regionToToggleSelector).slideToggle(function () {
225                    var visible = $(this).is(':visible');
226                    if (opts.saveState) {
227                        var id = $(toggle).prev().attr("id");
228                        var cookieId = id ? id.replace(/[^a-zA-Z0-9\-]+/g, "") : '';
229                        if (cookieId) {
230                            dnn.dom.setCookie(cookieId, visible, opts.cookieDays, '/', '', false, opts.cookieMilleseconds);
231                        }
232                    }
233                    if (visible) {
234                        $(this).trigger("onExpand");
235                    }
236                    else {
237                        $(this).trigger("onHide");
238                    }
239                });
240
241                e.preventDefault();
242                e.stopImmediatePropagation();
243                return false;
244            });
245
246            function collapsePanel($clicker, $region) {
247                $clicker.removeClass(opts.toggleClass);
248                $region.hide();
249                $this.trigger("onHide");
250            }
251
252            function expandPanel($clicker, $region) {
253                $clicker.addClass(opts.toggleClass);
254                $region.show();
255                $this.trigger("onExpand");
256            }
257
258            // walk over each selector and expand or collapse as necessary
259            $this.find(opts.sectionHeadSelector).each(function (indexInArray, valueOfElement) {
260                var $self = $(valueOfElement),
261                    elementId = $self.attr("id"),
262                    cookieId = elementId ? elementId.replace(/[^a-zA-Z0-9\-]+/g, "") : '',
263                    cookieValue = cookieId ? dnn.dom.getCookie(cookieId) : '',
264                    $clicker = $self.find(opts.clickToToggleIsolatedSelector),
265                    $region = $self.next(opts.regionToToggleSelector),
266                    $parentSeparator = $self.parents(opts.panelSeparatorSelector),
267                    groupPanelIndex = $parentSeparator.find(opts.sectionHeadSelector).index($self);
268
269                // default value
270                var isOpen = false;
271                if ((indexInArray === 0 && opts.defaultState == "first") || // cookie set to true OR first panel
272                    ($parentSeparator.length > 0 && groupPanelIndex === 0 && opts.defaultState == "first") || // grouping is used & its the first panel in its group
273                    (opts.defaultState == "open"))  // default open
274                {
275                    isOpen = true;
276                }
277                if (opts.saveState) {
278                    if (cookieValue == "true") {
279                        isOpen = true;
280                    }
281                    else if (cookieValue == "false") {
282                        isOpen = false;
283                    }
284                }
285
286                if (isOpen) {
287                    expandPanel($clicker, $region);
288                }
289                else {
290                    collapsePanel($clicker, $region);
291                }
292            });
293
294            // page validation integration - expand collapsed panels that contain tripped validators
295            $this.find(opts.validationTriggerSelector).click(function () {
296                if (typeof window.Page_ClientValidate != "undefined" && $.isFunction(window.Page_ClientValidate)) {
297                    if (!window.Page_ClientValidate(opts.validationGroup)) {
298                        $this.find(opts.invalidItemSelector).each(function () {
299                            var $parent = $(this).closest(opts.regionToToggleSelector);
300                            if ($parent.is(':hidden')) {
301                                $parent.prev(opts.sectionHeadSelector).find(opts.clickToToggleIsolatedSelector).click();
302                            }
303                        });
304                    }
305                }
306            });
307        });
308        return $wrap;
309    };
310
311    $.fn.dnnPanels.defaultOptions = {
312        clickToToggleSelector: 'h2.dnnFormSectionHead a',
313        sectionHeadSelector: '.dnnFormSectionHead',
314        regionToToggleSelector: 'fieldset',
315        toggleClass: 'dnnSectionExpanded',
316        clickToToggleIsolatedSelector: 'a',
317        validationTriggerSelector: '.dnnPrimaryAction',
318        invalidItemSelector: '.dnnFormError[style*="inline"]',
319        validationGroup: '',
320        panelSeparatorSelector: '.ui-tabs-panel',
321        cookieDays: 0,
322        cookieMilleseconds: 1200000, // twenty minutes
323        saveState: true,
324        defaultState: 'first' // open | closed | first
325    };
326
327})(jQuery);
328
329(function ($) {
330    $.fn.dnnPreview = function (options) {
331        var opts = $.extend({}, $.fn.dnnPreview.defaultOptions, options),
332        $wrap = this;
333
334        $wrap.each(function () {
335            var $this = $(this);
336            $this.find(opts.linkSelector).click(function (e) {
337                e.preventDefault();
338                var params = "?";
339                var skin, container;
340
341                if (opts.useComboBox) {
342                    var skinComboBox = $('#' + opts.skinSelector);
343                    var containerComboBox = $('#' + opts.containerSelector);;
344
345                    skin = skinComboBox.length ? skinComboBox[0].selectize.getValue() : '';
346                    container = containerComboBox.length ? containerComboBox[0].selectize.getValue() : '';
347                }
348                else {
349                    skin = $this.find(opts.skinSelector).val();
350                    container = $this.find(opts.containerSelector).val();
351                }
352                if (skin) {
353                    params += "SkinSrc=" + skin;
354                }
355                if (container) {
356                    if (skin) {
357                        params += "&";
358                    }
359                    params += "ContainerSrc=" + container;
360                }
361                if (opts.ModuleId) {
362                    if (params !== "?") {
363                        params += "&ModuleID=" + opts.ModuleId;
364                    } else {
365                        params += "ModuleID=" + opts.ModuleId;
366                    }
367                }
368                if (params != "?") {
369                    window.open(encodeURI(opts.baseUrl + params.replace(/.ascx/gi, '')), "skinpreview");
370                }
371                else {
372                    $.dnnAlert({ text: opts.noSelectionMessage, okText: opts.alertOkText, closeText: opts.alertCloseText });
373                }
374            });
375        });
376
377        return $wrap;
378    };
379
380    $.fn.dnnPreview.defaultOptions = {
381        baseUrl: window.location.protocol + "//" + window.location.host + window.location.pathname,
382        linkSelector: 'a.dnnSecondaryAction',
383        skinSelector: '',
384        containerSelector: '',
385        noSelectionMessage: 'Please select a preview option.',
386        alertOkText: 'Ok',
387        alertCloseText: 'close',
388        useComboBox: false
389    };
390
391})(jQuery);
392
393(function ($) {
394    $.fn.dnnExpandAll = function (options) {
395        var opts = $.extend({}, $.fn.dnnExpandAll.defaultOptions, options),
396        $elem = this;
397
398        if (($(opts.targetArea).find(opts.targetSelector + ':visible').length ===
399            $(opts.targetArea).find(opts.targetSelector + opts.targetExpandedSelector + ':visible').length)
400            && !$(this).hasClass('expanded')) {
401            $(this).addClass('expanded').text(opts.collapseText);
402        }
403
404        $elem.click(function (e) {
405            e.preventDefault();
406            var $this = $(this);
407            if ($this.hasClass('expanded')) {
408                $this.removeClass('expanded').text(opts.expandText);
409                $(opts.targetArea).find(opts.targetSelector + opts.targetExpandedSelector + ':visible').click();
410            }
411            else {
412                $this.addClass('expanded').text(opts.collapseText);
413                $(opts.targetArea).find(opts.targetSelector + ':visible').not(opts.targetExpandedSelector).click();
414            }
415
416            //stop event from called again
417            e.stopImmediatePropagation();
418        });
419
420        return $elem;
421    };
422    $.fn.dnnExpandAll.defaultOptions = {
423        expandText: 'Expand All',
424        collapseText: 'Collapse All',
425        targetArea: '#dnnHostSettings',
426        targetSelector: 'h2.dnnFormSectionHead a',
427        targetExpandedSelector: '.dnnSectionExpanded'
428    };
429})(jQuery);
430
431(function ($) {
432    $.fn.dnnTooltip = function (options) {
433        var opts = $.extend({}, $.fn.dnnTooltip.defaultOptions, options),
434        $wrap = this;
435
436        $wrap.each(function () {
437            var $this = $(this),
438                dnnFormHelp = $this.prev();
439            if ($this.data('initialized')) return;
440            dnnFormHelp.on('click', function (e) {
441                e.preventDefault();
442            });
443            var helpSelector = $this.find(opts.helpSelector);
444            $this.parent().css({ position: 'relative' });
445            $this.css({ position: 'absolute', right: '-29%' });
446            var hoverOnToolTip = false, hoverOnPd = false;
447
448            dnnFormHelp.hoverIntent({
449                over: function () {
450                    hoverOnPd = true;
451                    var tooltipHeight = helpSelector.height();
452                    var top = -(tooltipHeight + 30);
453                    if ((tooltipHeight + 30) <= $this.parent().offset().top) {
454                        helpSelector.parent().css({ top: top + 'px' });
455                        $this.find("div.dnnFormHelpContent span").addClass("bottomArrow");
456                        $this.find("div.dnnFormHelpContent span").removeClass("topArrow");
457
458                    } else {
459                        helpSelector.parent().css({ top: 30 + 'px' });                  
460                        $this.find("div.dnnFormHelpContent span").addClass("topArrow");
461                        $this.find("div.dnnFormHelpContent span").removeClass("bottomArrow");
462                    }
463                    helpSelector.css('visibility', 'visible');
464                },
465                out: function () {
466                    hoverOnPd = false;
467                    if (!$this.hasClass(opts.pinnedClass) && !hoverOnToolTip) {
468                        helpSelector.css('visibility', 'hidden');
469                    }
470                },
471                timeout: 200,
472                interval: 200
473            });
474
475            helpSelector.hover(function () { hoverOnToolTip = true; }, function () {
476                hoverOnToolTip = false;
477                if (!$this.hasClass(opts.pinnedClass) && !hoverOnPd) {
478                    helpSelector.css('visibility', 'hidden');
479                }
480            });
481
482            var pinHelper = helpSelector.find(opts.pinSelector);
483
484            pinHelper.on('click', function (e) {
485                e.preventDefault();
486                if ($this.hasClass(opts.pinnedClass)) {
487                    helpSelector.css({ "left": '0', "top": '0' })
488                        .css('visibility', 'hidden')
489                        .draggable('destroy');
490                    $this.removeClass(opts.pinnedClass);
491                }
492                else {
493
494                    $this.addClass(opts.pinnedClass);
495                    if ($.isFunction($().draggable)) {
496                        helpSelector.draggable();
497                    }
498                }
499            });
500
501            $this.data('initialized', 1);
502        });
503
504        return $wrap;
505    };
506
507    $.fn.dnnTooltip.defaultOptions = {
508        pinSelector: 'a.pinHelp',
509        helpSelector: '.dnnFormHelpContent',
510        pinnedClass: 'dnnTooltipPinned'
511    };
512
513})(jQuery);
514
515(function ($) {
516    var cb = function (e) {
517        if (!e) e = window.event;
518        e.cancelBubble = true;
519        if (e.stopPropagation) e.stopPropagation();
520    };
521
522    /* DNN customized checkbox/radiobox */
523    $.fn.dnnCheckbox = function (options) {
524        var settings = {
525            cls: 'dnnCheckbox'  /* checkbox  */
526            , labelClass: 'dnnBoxLabel'
527        };
528        settings = $.extend(settings, options || {});
529
530        var addEvents = function (object) {
531            var checked = object.checked,
532                disabled = object.disabled,
533                $object = $(object);
534
535            if (object.stateInterval)
536                clearInterval(object.stateInterval);
537
538            object.stateInterval = setInterval(
539                function () {
540                    if (object.disabled != disabled)
541                        $object.trigger((disabled = !!object.disabled) ? 'disable' : 'enable');
542                    if (object.checked != checked)
543                        $object.trigger((checked = !!object.checked) ? 'check' : 'uncheck');
544                },
545                10 /* in miliseconds.*/
546            );
547            return $object;
548        };
549
550        return this.each(function () {
551            var ch = this;
552
553            if ($(ch).data("checkBoxWrapped")) {
554                return;
555            }
556            $(ch).data("checkBoxWrapped", true);
557
558            if ($(this).hasClass('normalCheckBox') || $(this).hasClass('normalRadioButton')) return;
559            var parentCheckBoxHolder = $(this).closest('.normalCheckBox');
560            var parentRadioButtonHolder = $(this).closest('.normalRadioButton');
561            if (parentCheckBoxHolder.length || parentRadioButtonHolder.length) return;
562            var $ch = addEvents(ch);
563            if (ch.wrapper) ch.wrapper.remove();
564            ch.wrapper = $('<span class="' + settings.cls + '"><span class="mark"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFAAAAAAAApWe5zwAAAAF0Uk5TAEDm2GYAAAAMSURBVHjaYmAACDAAAAIAAU9tWeEAAAAASUVORK5CYII=" alt="checkbox" /></span></span>');
565            ch.wrapperInner = ch.wrapper.children('span:eq(0)');
566            ch.wrapper.hover(
567                function (e) { ch.wrapperInner.addClass(settings.cls + '-hover'); cb(e); },
568                function (e) { ch.wrapperInner.removeClass(settings.cls + '-hover'); cb(e); }
569            );
570
571            $ch.css({ position: 'absolute', zIndex: -1, opacity: 0 }).after(ch.wrapper);
572
573            var label, parentLabel = false;
574            label = $ch.closest('label');
575            if (!label.length)
576                label = false;
577            else
578                parentLabel = true;
579
580            if (!label && $ch.attr('id')) {
581                label = $('label[for="' + $ch.attr('id') + '"]');
582                if (!label.length) label = false;
583            }
584
585            if (label) {
586                label.addClass(settings.labelClass);
587                if (!parentLabel) {
588                    label.click(function (e) {
589                        clickHandler(e);
590                        return false;
591                    });
592                }
593                else {
594                    label.children().each(function () {
595                        var $this = $(this);
596                        if ($this.is('input')) return;
597
598                        $this.click(function (e) {
599                            clickHandler(e);
600                            return false;
601                        });
602                    });
603                }
604            }
605
606            if (!parentLabel) {
607                ch.wrapper.click(function (e) {
608                    clickHandler(e);
609                    return false;
610                });
611            }
612
613            function clickHandler(e) {
614                if (ch.disabled) {
615                    return;
616                }
617                $ch.triggerHandler('focus');
618                var previousChecked = ch.checked;
619                ch.click();
620                if (ch.checked == previousChecked && ch.type == 'checkbox') {
621                    ch.checked = !ch.checked;  //Fix for Firefox browser
622                }
623                $ch.trigger('change', [e]);
624                cb(e);
625            }
626
627            $ch.on('disable', function () { ch.wrapperInner.addClass(settings.cls + '-disabled'); }).on('enable', function () { ch.wrapperInner.removeClass(settings.cls + '-disabled'); });
628            $ch.on('check', function () { ch.wrapper.addClass(settings.cls + '-checked'); }).on('uncheck', function () { ch.wrapper.removeClass(settings.cls + '-checked'); });
629            $ch.on('focus', function (e) { if (!e.isTrigger) ch.wrapper.addClass(settings.cls + '-focus'); }).on('blur', function () { ch.wrapper.removeClass(settings.cls + '-focus'); });
630
631            /* Applying checkbox state */
632            if (ch.checked)
633                ch.wrapper.addClass(settings.cls + '-checked');
634            if (ch.disabled)
635                ch.wrapperInner.addClass(settings.cls + '-disabled');
636
637        });
638    };
639
640    $.fn.dnnHelperTipDestroy = function () {
641        return this.each(function () {
642            var pd = this;
643            if (pd.id) {
644                $('div[data-tipholder="' + pd.id + '"]').remove();
645            }
646        });
647    };
648
649    $.fn.dnnHelperTip = function (options) {
650        var settings = {
651            cls: 'dnnHelperTip',
652            helpContent: "This is hover helper tooltip",
653            holderId: '',
654            show: false // immediately show tooltip after call
655        };
656        settings = $.extend(settings, options || {});
657        return this.each(function () {
658            var pd = this,
659                $pd = $(this);
660            if (pd.tooltipWrapper) pd.tooltipWrapper.remove();
661
662            pd.tooltipWrapper = $('<div class="' + settings.cls + '" data-tipholder="' + settings.holderId + '"> <div class="dnnFormHelpContent dnnClear"><span class="dnnHelpText">' + settings.helpContent + '</span></div></div>');
663            $('body').append(pd.tooltipWrapper);
664            pd.tooltipWrapper.css({ position: 'absolute' });
665            pd.tooltipWrapperInner = $('.dnnFormHelpContent', pd.tooltipWrapper);
666
667            var tooltipHeight = pd.tooltipWrapperInner.height();
668            pd.tooltipWrapperInner.css({ left: '-10px', top: -(tooltipHeight + 30) + 'px' });
669            var hoverOnPd = false;
670            $pd.hover(
671                function () {
672                    hoverOnPd = true;
673                    setTimeout(function () {
674                        if (hoverOnPd)
675                            pd.tooltipWrapperInner.css('visibility', 'visible');
676                    }, 400);
677                },
678                function () {
679                    hoverOnPd = false;
680                    setTimeout(function () {
681                        if (!hoverOnPd)
682                            pd.tooltipWrapperInner.css('visibility', 'hidden');
683                    }, 400);
684
685                });
686
687            if (settings.show) {
688                hoverOnPd = true;
689                setTimeout(function () {
690                    pd.tooltipWrapperInner.css('visibility', 'visible');
691                }, 400);
692            }
693
694            $pd.on('mousemove', function (e) {
695                var x = e.pageX; var y = e.pageY;
696                var pos = $('body').css('position');
697                if (pos == 'relative') y -= 38;
698                pd.tooltipWrapper.css({ left: x + 'px', top: y + 'px', 'z-index': '99999' });
699            });
700        });
701    };
702
703    $.fn.dnnProgressbar = function () {
704        var $pd = $(this),
705            pd = this;
706
707        if (pd.tooltipWrapper) pd.tooltipWrapper.remove();
708        pd.tooltipWrapper = $('<div class="dnnTooltip"> <div class="dnnFormHelpContent dnnClear"><span class="dnnHelpText"></span></div></div>').insertAfter($pd);
709        pd.tooltipWrapperInner = $('.dnnFormHelpContent', pd.tooltipWrapper);
710        pd.tooltipWrapperInner.css({ width: '32px', padding: '7px' });
711        $pd.parent().css({ position: 'relative' });
712
713        var hoverOnToolTip = false, hoverOnPd = false;
714        $pd.hoverIntent({
715            over: function () {
716                hoverOnPd = true;
717                var val = $(this).children(':first').progressbar('value');
718                pd.update(val);
719                pd.tooltipWrapperInner.css('visibility', 'visible');
720
721            },
722            out: function () {
723                hoverOnPd = false;
724                if (!hoverOnToolTip) {
725                    pd.tooltipWrapperInner.css('visibility', 'hidden');
726                }
727            },
728            timeout: 200,
729            interval: 200
730        });
731
732        pd.tooltipWrapperInner.hover(function () { hoverOnToolTip = true; }, function () {
733            hoverOnToolTip = false;
734            if (!hoverOnPd) {
735                pd.tooltipWrapperInner.hide();
736            }
737        });
738
739        pd.update = function (value) {
740            pd.tooltipWrapperInner.find('span').html(value + ' %');
741            var pdTop = $pd.position().top,
742			    tooltipHeight = pd.tooltipWrapperInner.height();
743
744            pdTop -= (tooltipHeight + 10);
745            var pdLeft = value > 50 ? (value - 4) + '%' : value > 0 ? (value - 2) + '%' : '10px';
746            pd.tooltipWrapper.css({ position: 'absolute', left: pdLeft, top: pdTop + 'px' });
747        };
748
749        return this;
750    };
751
752    $.fn.dnnSpinner = function (options) {
753        var opt = $.extend({
754            type: 'range',
755            typedata: '',
756            width: '150px',
757            looping: false
758        }, options);
759
760        var otypedata;
761
762        if (options != null && options.typedata != null) {
763            otypedata = $.extend({
764                min: 1,
765                max: 10,
766                interval: 1,
767                decimalplaces: 0
768            }, options.typedata);
769        }
770        else {
771            otypedata = $.extend({
772                min: 1,
773                max: 10,
774                interval: 1,
775                decimalplaces: 0
776            });
777        }
778        opt.typedata = otypedata;
779
780        var inputControl = this;
781        if (!inputControl.is(':text'))
782            return inputControl;
783
784        if (inputControl.hasClass('dnnSpinnerInput')) {
785            return inputControl;
786        }
787        else {
788            inputControl.addClass('dnnSpinnerInput');
789        }
790
791        var strContainerDiv = '';
792        strContainerDiv += '<div class="dnnSpinner">';
793        strContainerDiv += '<div class="dnnSpinnerDisplay"></div>';
794        strContainerDiv += '<div class="dnnSpinnerCtrl">';
795        strContainerDiv += '<a class="dnnSpinnerTopButton"></a>';
796        strContainerDiv += '<a class="dnnSpinnerBotButton"></a>';
797        strContainerDiv += '</div></div>';
798        var objContainerDiv = $(strContainerDiv).insertAfter(inputControl);
799        inputControl.insertAfter($("div.dnnSpinnerDisplay", objContainerDiv));
800        $("div.dnnSpinnerDisplay", objContainerDiv).click(function () {
801            if (opt.type == 'range') {
802                var displayCtrl = $(this);
803                var innerInput = $('input[type="text"]', displayCtrl);
804                if (innerInput.length < 1) {
805                    var originalVal = displayCtrl.html();
806                    innerInput = $('<input type="text" />').val(originalVal);
807                    displayCtrl.html(innerInput);
808                    innerInput.blur(function () {
809                        var newVal = $(this).val();
810                        if (newVal > opt.typedata.max) {
811                            newVal = opt.typedata.max;
812                        }
813                        if (newVal < opt.typedata.min) {
814                            newVal = opt.typedata.min;
815                        }
816                        $(this).remove();
817                        selectedValue = parseInt(newVal);
818                        inputControl.val(newVal);
819                        displayCtrl.html(newVal);
820                    }).keypress(function (e) {
821                        var regex = new RegExp("^[0-9]+$");
822                        var key = String.fromCharCode(!e.charCode ? e.which : e.charCode);
823                        if (!regex.test(key)) {
824                            event.preventDefault();
825                            return false;
826                        }
827                        return true;
828                    });
829                }
830                innerInput.focus();
831            }
832
833            inputControl.triggerHandler('focus');
834        });
835        inputControl.css('display', 'none');
836
837        switch (opt.type) {
838            case 'range':
839                if (opt.defaultVal < opt.typedata.min || opt.defaultVal > opt.typedata.max) {
840                    opt.defaultVal = opt.typedata.min;
841                }
842                if (opt.defaultVal % opt.typedata.interval > 0) {
843                    opt.defaultVal = parseInt((opt.defaultVal / opt.typedata.interval).toFixed(0)) * opt.typedata.interval;
844                }
845                inputControl.val(opt.defaultVal.toFixed(opt.typedata.decimalplaces));
846                ($("div.dnnSpinnerDisplay", objContainerDiv)).html(opt.defaultVal.toFixed(opt.typedata.decimalplaces));
847                var selectedValue = opt.defaultVal;
848                if ((opt.typedata.max - opt.typedata.min) > opt.typedata.interval) {
849                    $("a.dnnSpinnerTopButton", objContainerDiv).click(function () {
850
851                        if ((selectedValue + opt.typedata.interval) <= opt.typedata.max || opt.looping) {
852                            if ((selectedValue + opt.typedata.interval) > opt.typedata.max) {
853                                selectedValue = opt.typedata.min - opt.typedata.interval;
854                            }
855                            var valueData = (selectedValue + opt.typedata.interval).toFixed(opt.typedata.decimalplaces);
856                            selectedValue += opt.typedata.interval;
857                            ($("div.dnnSpinnerDisplay", objContainerDiv)).html(valueData);
858                            inputControl.val(valueData);
859                        }
860                        inputControl.triggerHandler('focus');
861                        return false;
862                    });
863
864                    $("a.dnnSpinnerBotButton", objContainerDiv).click(function () {
865                        if ((selectedValue - opt.typedata.interval) >= opt.typedata.min || opt.looping) {
866                            if ((selectedValue - opt.typedata.interval) < opt.typedata.min) {
867                                selectedValue = opt.typedata.max + opt.typedata.interval;
868                            }
869                            var valueData = (selectedValue - opt.typedata.interval).toFixed(opt.typedata.decimalplaces);
870                            selectedValue -= opt.typedata.interval;
871                            ($("div.dnnSpinnerDisplay", objContainerDiv)).html(valueData);
872                            inputControl.val(valueData);
873                        }
874                        inputControl.triggerHandler('focus');
875                        return false;
876                    });
877                }
878
879                break;
880            case 'list':
881                if (!opt.typedata.list || opt.typedata.list.lenght == 0) {
882                    return inputControl;
883                }
884
885                var listItems = opt.typedata.list.split(',');
886                var selectedIndex = jQuery.inArray(opt.defaultVal, listItems);
887                if (selectedIndex < 0) {
888                    selectedIndex = 0;
889                    opt.defaultVal = listItems[0];
890                }
891
892                inputControl.val(opt.defaultVal);
893                ($("div.dnnSpinnerDisplay", objContainerDiv)).html(opt.defaultVal);
894
895                if (listItems.length > 1) {
896                    // attach events;
897                    $("a.dnnSpinnerBotButton", objContainerDiv).click(function () {
898                        if (selectedIndex < (listItems.length - 1) || opt.looping) {
899                            if (selectedIndex == listItems.length - 1) {
900                                selectedIndex = -1;
901                            }
902                            selectedIndex++;
903                            var valueData = listItems[selectedIndex];
904                            ($("div.dnnSpinnerDisplay", objContainerDiv)).html(valueData);
905                            inputControl.val(valueData);
906                        }
907                        inputControl.triggerHandler('focus');
908                        return false;
909                    });
910
911                    $("a.dnnSpinnerTopButton", objContainerDiv).click(function () {
912                        if (selectedIndex > 0 || opt.looping) {
913                            if (selectedIndex == 0) {
914                                selectedIndex = listItems.length;
915                            }
916                            selectedIndex--;
917                            var valueData = listItems[selectedIndex];
918                            ($("div.dnnSpinnerDisplay", objContainerDiv)).html(valueData);
919                            inputControl.val(valueData);
920                        }
921                        inputControl.triggerHandler('focus');
922                        return false;
923                    });
924                }
925
926                break;
927        };
928        return inputControl;
929    };
930})(jQuery);
931
932(function ($) {
933    $.fn.dnnAutocomplete = function (options) {
934        var url;
935        if (arguments.length > 1) {
936            url = options;
937            options = arguments[1];
938            options.url = url;
939        } else if (typeof options === 'string') {
940            url = options;
941            options = { url: url };
942        }
943        var opts = $.extend({}, $.fn.dnnAutocomplete.defaults, options);
944        return this.each(function () {
945            var $this = $(this);
946            $this.data('autocompleter', new $.dnnAutocompleter(
947                $this,
948                $.meta ? $.extend({}, opts, $this.data()) : opts
949            ));
950        });
951    };
952
953    $.fn.dnnAutocomplete.defaults = {
954        inputClass: 'dnn_acInput',
955        loadingClass: 'dnn_acLoading',
956        resultsClass: 'dnn_acResults',
957        selectClass: 'dnn_acSelect',
958        queryParamName: 'q',
959        contentTypeParamName: 'contentTypeId',
960        extraParams: {},
961        remoteDataType: false,
962        lineSeparator: '\n',
963        cellSeparator: '|',
964        minChars: 2,
965        maxItemsToShow: 10,
966        delay: 400,
967        useCache: false,
968        maxCacheLength: 10,
969        matchSubset: true,
970        matchCase: false,
971        matchInside: true,
972        mustMatch: false,
973        selectFirst: false,
974        selectOnly: false,
975        showResult: null,
976        preventDefaultReturn: 1,
977        preventDefaultTab: 0,
978        autoFill: false,
979        filterResults: true,
980        sortResults: true,
981        sortFunction: null,
982        onItemSelect: null,
983        onNoMatch: null,
984        onFinish: null,
985        matchStringConverter: null,
986        beforeUseConverter: null,
987        autoWidth: 'min-width',
988        useDelimiter: false,
989        delimiterChar: ',',
990        delimiterKeyCode: 188,
991        processData: null,
992        onError: null,
993        moduleId: null // dnn Module Id context if needed
994    };
995
996    var sanitizeResult = function (result) {
997        var value, data;
998        var type = typeof result;
999        if (type === 'string') {
1000            value = result;
1001            data = {};
1002        } else if ($.isArray(result)) {
1003            value = result[0];
1004            data = result.slice(1);
1005        } else if (type === 'object') {
1006            value = result.value;
1007            data = result.data;
1008        } else value = '';
1009        value = String(value);
1010        if (typeof data !== 'object') {
1011            data = {};
1012        }
1013        return {
1014            value: value,
1015            data: data
1016        };
1017    };
1018
1019    var sanitizeInteger = function (value, stdValue, options) {
1020        var num = parseInt(value, 10);
1021        options = options || {};
1022        if (isNaN(num) || (options.min && num < options.min)) {
1023            num = stdValue;
1024        }
1025        return num;
1026    };
1027
1028    var makeUrlParam = function (name, value) {
1029        return [name, encodeURIComponent(value)].join('=');
1030    };
1031
1032    var makeUrl = function (url, params) {
1033        var urlAppend = [];
1034        $.each(params, function (index, value) {
1035            urlAppend.push(makeUrlParam(index, value));
1036        });
1037        if (urlAppend.length) {
1038            url += url.indexOf('?') === -1 ? '?' : '&';
1039            url += urlAppend.join('&');
1040        }
1041        return url;
1042    };
1043
1044    var sortValueAlpha = function (a, b, matchCase) {
1045        a = String(a.value);
1046        b = String(b.value);
1047        if (!matchCase) {
1048            a = a.toLowerCase();
1049            b = b.toLowerCase();
1050        }
1051        if (a > b) {
1052            return 1;
1053        }
1054        if (a < b) {
1055            return -1;
1056        }
1057        return 0;
1058    };
1059
1060    $.dnnAutocompleter = function ($elem, options) {
1061
1062        if (!$elem || !($elem instanceof $) || $elem.length !== 1 || $elem.get(0).tagName.toUpperCase() !== 'INPUT') {
1063            throw new Error('Invalid parameter for dnnAutocompleter, jQuery object with one element with INPUT tag expected.');
1064        }
1065
1066        var self = this;
1067        this.options = options;
1068        this.cacheData_ = {};
1069        this.cacheLength_ = 0;
1070        this.selectClass_ = 'jquery-autocomplete-selected-item';
1071        this.keyTimeout_ = null;
1072        this.finishTimeout_ = null;
1073        this.lastKeyPressed_ = null;
1074        this.lastProcessedValue_ = null;
1075        this.lastSelectedValue_ = null;
1076        this.active_ = false;
1077        this.finishOnBlur_ = true;
1078
1079        this.options.minChars = sanitizeInteger(this.options.minChars, $.fn.dnnAutocomplete.defaults.minChars, { min: 0 });
1080        this.options.maxItemsToShow = sanitizeInteger(this.options.maxItemsToShow, $.fn.dnnAutocomplete.defaults.maxItemsToShow, { min: 0 });
1081        this.options.maxCacheLength = sanitizeInteger(this.options.maxCacheLength, $.fn.dnnAutocomplete.defaults.maxCacheLength, { min: 1 });
1082        this.options.delay = sanitizeInteger(this.options.delay, $.fn.dnnAutocomplete.defaults.delay, { min: 0 });
1083        if (this.options.preventDefaultReturn != 2) {
1084            this.options.preventDefaultReturn = this.options.preventDefaultReturn ? 1 : 0;
1085        }
1086        if (this.options.preventDefaultTab != 2) {
1087            this.options.preventDefaultTab = this.options.preventDefaultTab ? 1 : 0;
1088        }
1089
1090        this.dom = {};
1091        this.dom.$elem = $elem;
1092        this.dom.$elem.attr('autocomplete', 'off').addClass(this.options.inputClass);
1093        this.dom.$results = $('<div></div>').hide().addClass(this.options.resultsClass).css({
1094            position: 'absolute'
1095        });
1096        $('body').append(this.dom.$results);
1097        $elem.keydown(function (e) {
1098            self.lastKeyPressed_ = e.keyCode;
1099            switch (self.lastKeyPressed_) {
1100                case self.options.delimiterKeyCode: // comma = 188
1101                    if (self.options.useDelimiter && self.active_) {
1102                        self.selectCurrent();
1103                    }
1104                    break;
1105
1106                    // ignore navigational & special keys
1107                case 35: // end
1108                case 36: // home
1109                case 16: // shift
1110                case 17: // ctrl
1111                case 18: // alt
1112                case 37: // left
1113                case 39: // right
1114                    break;
1115
1116                case 38: // up
1117                    e.preventDefault();
1118                    if (self.active_) {
1119                        self.focusPrev();
1120                    } else {
1121                        self.activate();
1122                    }
1123                    return false;
1124
1125                case 40: // down
1126                    e.preventDefault();
1127                    if (self.active_) {
1128                        self.focusNext();
1129                    } else {
1130                        self.activate();
1131                    }
1132                    return false;
1133
1134                case 9: // tab
1135                    if (self.active_) {
1136                        self.selectCurrent();
1137                        if (self.options.preventDefaultTab) {
1138                            e.preventDefault();
1139                            return false;
1140                        }
1141                    }
1142                    if (self.options.preventDefaultTab === 2) {
1143                        e.preventDefault();
1144                        return false;
1145                    }
1146                    break;
1147
1148                case 13: // return
1149                    if (self.active_) {
1150                        self.selectCurrent();
1151                        if (self.options.preventDefaultReturn) {
1152                            e.preventDefault();
1153                            return false;
1154                        }
1155                    }
1156                    if (self.options.preventDefaultReturn === 2) {
1157                        e.preventDefault();
1158                        return false;
1159                    }
1160                    break;
1161
1162                case 27: // escape
1163                    if (self.active_) {
1164                        e.preventDefault();
1165                        self.deactivate(true);
1166                        return false;
1167                    }
1168                    break;
1169
1170                default:
1171                    self.activate();
1172
1173            }
1174            return true;
1175        });
1176
1177        var onBlurFunction = function () {
1178            self.deactivate(true);
1179        };
1180        $elem.blur(function () {
1181            if (self.finishOnBlur_) {
1182                self.finishTimeout_ = setTimeout(onBlurFunction, 1000);
1183            }
1184        });
1185
1186        $elem.parents('form').on('submit', onBlurFunction);
1187
1188    };
1189
1190    $.dnnAutocompleter.prototype.position = function () {
1191        var offset = this.dom.$elem.offset();
1192        var height = this.dom.$results.outerHeight();
1193        var totalHeight = window.outerHeight;
1194        var inputBottom = offset.top + this.dom.$elem.outerHeight();
1195        var bottomIfDown = inputBottom + height;
1196        // Set autocomplete results at the bottom of input
1197        var position = { top: inputBottom, left: offset.left };
1198        if (bottomIfDown > totalHeight) {
1199            // Try to set autocomplete results at the top of input
1200            var topIfUp = offset.top - height;
1201            if (topIfUp >= 0) {
1202                position.top = topIfUp;
1203            }
1204        }
1205        this.dom.$results.css(position);
1206    };
1207
1208    $.dnnAutocompleter.prototype.cacheRead = function (filter) {
1209        var filterLength, searchLength, search, maxPos, pos;
1210        if (this.options.useCache) {
1211            filter = String(filter);
1212            filterLength = filter.length;
1213            if (this.options.matchSubset) {
1214                searchLength = 1;
1215            } else {
1216                searchLength = filterLength;
1217            }
1218            while (searchLength <= filterLength) {
1219                if (this.options.matchInside) {
1220                    maxPos = filterLength - searchLength;
1221                } else {
1222                    maxPos = 0;
1223                }
1224                pos = 0;
1225                while (pos <= maxPos) {
1226                    search = filter.substr(0, searchLength);
1227                    if (this.cacheData_[search] !== undefined) {
1228                        return this.cacheData_[search];
1229                    }
1230                    pos++;
1231                }
1232                searchLength++;
1233            }
1234        }
1235        return false;
1236    };
1237
1238    $.dnnAutocompleter.prototype.cacheWrite = function (filter, data) {
1239        if (this.options.useCache) {
1240            if (this.cacheLength_ >= this.options.maxCacheLength) {
1241                this.cacheFlush();
1242            }
1243            filter = String(filter);
1244            if (this.cacheData_[filter] !== undefined) {
1245                this.cacheLength_++;
1246            }
1247            this.cacheData_[filter] = data;
1248            return this.cacheData_[filter];
1249        }
1250        return false;
1251    };
1252
1253    $.dnnAutocompleter.prototype.cacheFlush = function () {
1254        this.cacheData_ = {};
1255        this.cacheLength_ = 0;
1256    };
1257
1258    $.dnnAutocompleter.prototype.callHook = function (hook, data) {
1259        var f = this.options[hook];
1260        if (f && $.isFunction(f)) {
1261            return f(data, this);
1262        }
1263        return false;
1264    };
1265
1266    $.dnnAutocompleter.prototype.activate = function () {
1267        var self = this;
1268        if (this.keyTimeout_) {
1269            clearTimeout(this.keyTimeout_);
1270        }
1271        this.keyTimeout_ = setTimeout(function () {
1272            self.activateNow();
1273        }, this.options.delay);
1274    };
1275
1276    $.dnnAutocompleter.prototype.activateNow = function () {
1277        var value = this.beforeUseConverter(this.dom.$elem.val());
1278        if (value !== this.lastProcessedValue_ && value !== this.lastSelectedValue_) {
1279            this.fetchData(value);
1280        }
1281    };
1282
1283    $.dnnAutocompleter.prototype.fetchData = function (value) {
1284        var self = this;
1285        var processResults = function (results, filter) {
1286            if (self.options.processData) {
1287                results = self.options.processData(results);
1288            }
1289            self.showResults(self.filterResults(results, filter), filter);
1290        };
1291        this.lastProcessedValue_ = value;
1292        if (value.length < this.options.minChars) {
1293            processResults([], value);
1294        } else if (this.options.data) {
1295            processResults(this.options.data, value);
1296        } else {
1297            this.fetchRemoteData(value, function (remoteData) {
1298                processResults(remoteData, value);
1299            });
1300        }
1301    };
1302
1303    $.dnnAutocompleter.prototype.fetchRemoteData = function (filter, callback) {
1304        var data = this.cacheRead(filter);
1305        if (data) {
1306            callback(data);
1307        } else {
1308            var self = this;
1309            var ajaxCallback = function (d) {
1310                var parsed = false;
1311                if (d !== false) {
1312                    parsed = self.parseRemoteData(d);
1313                    self.cacheWrite(filter, parsed);
1314                }
1315                self.dom.$elem.removeClass(self.options.loadingClass);
1316                callback(parsed);
1317            };
1318
1319            this.dom.$elem.addClass(this.options.loadingClass);
1320            // DNN service framework attached if needed
1321            var services = self.options.moduleId ? ($.dnnSF ? $.dnnSF(self.options.moduleId) : null) : null;
1322            $.ajax({
1323                url: this.makeUrl(filter),
1324                beforeSend: services ? services.setModuleHeaders : null,
1325                success: ajaxCallback,
1326                error: function (jqXhr, textStatus, errorThrown) {
1327                    if ($.isFunction(self.options.onError)) {
1328                        self.options.onError(jqXhr, textStatus, errorThrown);
1329                    } else {
1330                        ajaxCallback(false);
1331                    }
1332                },
1333                type: 'GET',
1334                dataType: 'json',
1335                contentType: "application/json"
1336            });
1337        }
1338    };
1339
1340    $.dnnAutocompleter.prototype.setExtraParam = function (name, value) {
1341        var index = $.trim(String(name));
1342        if (index) {
1343            if (!this.options.extraParams) {
1344                this.options.extraParams = {};
1345            }
1346            if (this.options.extraParams[index] !== value) {
1347                this.options.extraParams[index] = value;
1348                this.cacheFlush();
1349            }
1350        }
1351    };
1352
1353    $.dnnAutocompleter.prototype.makeUrl = function (param) {
1354        var url = this.options.url;
1355        var params = {};
1356        params[this.options.queryParamName] = param;
1357        return makeUrl(url, params);
1358    };
1359
1360    $.dnnAutocompleter.prototype.parseRemoteData = function (remoteData) {
1361        var data = remoteData;
1362        if (typeof data['d'] != 'undefined') {
1363            data = $.parseJSON(data['d']);
1364        }
1365        return data;
1366    };
1367
1368    $.dnnAutocompleter.prototype.filterResult = function (result, filter) {
1369        if (!result.value) {
1370            return false;
1371        }
1372        if (this.options.filterResults) {
1373            var pattern = this.matchStringConverter(filter);
1374            var testValue = this.matchStringConverter(result.value);
1375            if (!this.options.matchCase) {
1376                pattern = pattern.toLowerCase();
1377                testValue = testValue.toLowerCase();
1378            }
1379            var patternIndex = testValue.indexOf(pattern);
1380            if (this.options.matchInside) {
1381                return patternIndex > -1;
1382            } else {
1383                return patternIndex === 0;
1384            }
1385        }
1386        return true;
1387    };
1388
1389    $.dnnAutocompleter.prototype.filterResults = function (results, filter) {
1390        var filtered = [];
1391        var i, result;
1392
1393        for (i = 0; i < results.length; i++) {
1394            result = sanitizeResult(results[i]);
1395            if (this.filterResult(result, filter)) {
1396                filtered.push(result);
1397            }
1398        }
1399        if (this.options.sortResults) {
1400            filtered = this.sortResults(filtered, filter);
1401        }
1402        if (this.options.maxItemsToShow > 0 && this.options.maxItemsToShow < filtered.length) {
1403            filtered.length = this.options.maxItemsToShow;
1404        }
1405        return filtered;
1406    };
1407
1408    $.dnnAutocompleter.prototype.sortResults = function (results, filter) {
1409        var self = this;
1410        var sortFunction = this.options.sortFunction;
1411        if (!$.isFunction(sortFunction)) {
1412            sortFunction = function (a, b) {
1413                return sortValueAlpha(a, b, self.options.matchCase);
1414            };
1415        }
1416        results.sort(function (a, b) {
1417            return sortFunction(a, b, filter, self.options);
1418        });
1419        return results;
1420    };
1421
1422    $.dnnAutocompleter.prototype.matchStringConverter = function (s, a, b) {
1423        var converter = this.options.matchStringConverter;
1424        if ($.isFunction(converter)) {
1425            s = converter(s, a, b);
1426        }
1427        return s;
1428    };
1429
1430    $.dnnAutocompleter.prototype.beforeUseConverter = function (s, a, b) {
1431        s = this.getValue();
1432        var converter = this.options.beforeUseConverter;
1433        if ($.isFunction(converter)) {
1434            s = converter(s, a, b);
1435        }
1436        return s;
1437    };
1438
1439    $.dnnAutocompleter.prototype.enableFinishOnBlur = function () {
1440        this.finishOnBlur_ = true;
1441    };
1442
1443    $.dnnAutocompleter.prototype.disableFinishOnBlur = function () {
1444        this.finishOnBlur_ = false;
1445    };
1446
1447    $.dnnAutocompleter.prototype.createItemFromResult = function (result, filter) {
1448        var self = this;
1449        var $li = $('<li>' + this.showResult(result.value, result.data, filter) + '</li>');
1450        $li.data({ value: result.value, data: result.data })
1451            .click(function () {
1452                self.selectItem($li);
1453            })
1454            .mousedown(self.disableFinishOnBlur)
1455            .mouseup(self.enableFinishOnBlur)
1456        ;
1457        return $li;
1458    };
1459
1460    $.dnnAutocompleter.prototype.getItems = function () {
1461        return $('>ul>li', this.dom.$results);
1462    };
1463
1464    $.dnnAutocompleter.prototype.showResults = function (results, filter) {
1465        var numResults = results.length;
1466        var self = this;
1467        var $ul = $('<ul></ul>');
1468        var i, result, $li, autoWidth, first = false, $first = false;
1469
1470        if (numResults) {
1471            for (i = 0; i < numResults; i++) {
1472                result = results[i];
1473                $li = this.createItemFromResult(result, filter);
1474                $ul.append($li);
1475                if (first === false) {
1476                    first = String(result.value);
1477                    $first = $li;
1478                    $li.addClass(this.options.firstItemClass);
1479                }
1480                if (i === numResults - 1) {
1481                    $li.addClass(this.options.lastItemClass);
1482                }
1483            }
1484
1485            this.dom.$results.html($ul).show();
1486
1487            // Always recalculate position since window size or
1488            // input element location may have changed.
1489            this.position();
1490            if (this.options.autoWidth) {
1491                autoWidth = this.dom.$elem.outerWidth() - this.dom.$results.outerWidth() + this.dom.$results.width();
1492                this.dom.$results.css(this.options.autoWidth, autoWidth);
1493            }
1494            this.getItems().hover(
1495                function () { self.focusItem(this); },
1496                function () { /* void */ }
1497            );
1498            if (this.autoFill(first, filter) || this.options.selectFirst || (this.options.selectOnly && numResults === 1)) {
1499                this.focusItem($first);
1500            }
1501            this.active_ = true;
1502
1503            //Select the first one as default
1504            this.focusNext();
1505
1506        } else {
1507            this.hideResults();
1508            this.active_ = false;
1509        }
1510    };
1511
1512    $.dnnAutocompleter.prototype.showResult = function (value, data, filter) {
1513        if ($.isFunction(this.options.showResult)) {
1514            return this.options.showResult(value, data);
1515        } else {
1516            // add highlight keywords
1517            var regex = new RegExp('(' + filter + ')', 'gi');
1518            return value.replace(regex, function ($0, $1) {
1519                return ('<b>' + $1 + '</b>');
1520            });
1521        }
1522    };
1523
1524    $.dnnAutocompleter.prototype.autoFill = function (value, filter) {
1525        var lcValue, lcFilter, valueLength, filterLength;
1526        if (this.options.autoFill && this.lastKeyPressed_ !== 8) {
1527            lcValue = String(value).toLowerCase();
1528            lcFilter = String(filter).toLowerCase();
1529            valueLength = value.length;
1530            filterLength = filter.length;
1531            if (lcValue.substr(0, filterLength) === lcFilter) {
1532                var d = this.getDelimiterOffsets();
1533                var pad = d.start ? ' ' : ''; // if there is a preceding delimiter
1534                this.setValue(pad + value);
1535                var start = filterLength + d.start + pad.length;
1536                var end = valueLength + d.start + pad.length;
1537                this.selectRange(start, end);
1538                return true;
1539            }
1540        }
1541        return false;
1542    };
1543
1544    $.dnnAutocompleter.prototype.focusNext = function () {
1545        this.focusMove(+1);
1546    };
1547
1548    $.dnnAutocompleter.prototype.focusPrev = function () {
1549        this.focusMove(-1);
1550    };
1551
1552    $.dnnAutocompleter.prototype.focusMove = function (modifier) {
1553        var $items = this.getItems();
1554        modifier = sanitizeInteger(modifier, 0);
1555        if (modifier) {
1556            for (var i = 0; i < $items.length; i++) {
1557                if ($($items[i]).hasClass(this.selectClass_)) {
1558                    this.focusItem(i + modifier);
1559                    return;
1560                }
1561            }
1562        }
1563        this.focusItem(0);
1564    };
1565
1566    $.dnnAutocompleter.prototype.focusItem = function (item) {
1567        var $item, $items = this.getItems();
1568        if ($items.length) {
1569            $items.removeClass(this.selectClass_).removeClass(this.options.selectClass);
1570            if (typeof item === 'number') {
1571                if (item < 0) {
1572                    item = 0;
1573                } else if (item >= $items.length) {
1574                    item = $items.length - 1;
1575                }
1576                $item = $($items[item]);
1577            } else {
1578                $item = $(item);
1579            }
1580            if ($item) {
1581                $item.addClass(this.selectClass_).addClass(this.options.selectClass);
1582            }
1583        }
1584    };
1585
1586    $.dnnAutocompleter.prototype.selectCurrent = function () {
1587        var $item = $('li.' + this.selectClass_, this.dom.$results);
1588        if ($item.length === 1) {
1589            this.selectItem($item);
1590        } else {
1591            this.deactivate(false);
1592        }
1593    };
1594
1595    $.dnnAutocompleter.prototype.selectItem = function ($li) {
1596        var value = $li.data('value');
1597        var data = $li.data('data');
1598        var displayValue = this.displayValue(value, data);
1599        var processedDisplayValue = this.beforeUseConverter(displayValue);
1600        this.lastProcessedValue_ = processedDisplayValue;
1601        this.lastSelectedValue_ = processedDisplayValue;
1602        var d = this.getDelimiterOffsets();
1603        var delimiter = this.options.delimiterChar;
1604        var elem = this.dom.$elem;
1605        var extraCaretPos = 0;
1606        if (this.options.useDelimiter) {
1607            // if there is a preceding delimiter, add a space after the delimiter
1608            if (elem.val().substring(d.start - 1, d.start) == delimiter && delimiter != ' ') {
1609                displayValue = ' ' + displayValue;
1610            }
1611            // if there is not already a delimiter trailing this value, add it
1612            if (elem.val().substring(d.end, d.end + 1) != delimiter && this.lastKeyPressed_ != this.options.delimiterKeyCode) {
1613                displayValue = displayValue + delimiter;
1614            } else {
1615                // move the cursor after the existing trailing delimiter
1616                extraCaretPos = 1;
1617            }
1618        }
1619        this.setValue(displayValue);
1620        this.setCaret(d.start + displayValue.length + extraCaretPos);
1621        this.callHook('onItemSelect', { value: value, data: data });
1622        this.deactivate(true);
1623        elem.trigger('result', value);
1624    };
1625
1626    $.dnnAutocompleter.prototype.displayValue = function (value, data) {
1627        if ($.isFunction(this.options.displayValue)) {
1628            return this.options.displayValue(value, data);
1629        }
1630        return value;
1631    };
1632
1633    $.dnnAutocompleter.prototype.hideResults = function () {
1634        this.dom.$results.hide();
1635    };
1636
1637    $.dnnAutocompleter.prototype.deactivate = function (finish) {
1638        if (this.finishTimeout_) {
1639            clearTimeout(this.finishTimeout_);
1640        }
1641        if (this.keyTimeout_) {
1642            clearTimeout(this.keyTimeout_);
1643        }
1644        if (finish) {
1645            if (this.lastProcessedValue_ !== this.lastSelectedValue_) {
1646                if (this.options.mustMatch) {
1647                    this.setValue('');
1648                }
1649                this.callHook('onNoMatch');
1650            }
1651            if (this.active_) {
1652                this.callHook('onFinish');
1653            }
1654            this.lastKeyPressed_ = null;
1655            this.lastProcessedValue_ = null;
1656            this.lastSelectedValue_ = null;
1657            this.active_ = false;
1658        }
1659        this.hideResults();
1660    };
1661
1662    $.dnnAutocompleter.prototype.selectRange = function (start, end) {
1663        var input = this.dom.$elem.get(0);
1664        if (input.setSelectionRange) {
1665            input.focus();
1666            input.setSelectionRange(start, end);
1667        } else if (input.createTextRange) {
1668            var range = input.createTextRange();
1669            range.collapse(true);
1670            range.moveEnd('character', end);
1671            range.moveStart('character', start);
1672            range.select();
1673        }
1674    };
1675
1676    $.dnnAutocompleter.prototype.setCaret = function (pos) {
1677        this.selectRange(pos, pos);
1678    };
1679
1680    $.dnnAutocompleter.prototype.getCaret = function () {
1681        var elem = this.dom.$elem, s, e, range;
1682        if (!$.support.cssFloat) {
1683            // ie
1684            var selection = document.selection;
1685            if (elem[0].tagName.toLowerCase() != 'textarea') {
1686                var val = elem.val();
1687                range = selection.createRange().duplicate();
1688                range.moveEnd('character', val.length);
1689                s = (range.text == '' ? val.length : val.lastIndexOf(range.text));
1690                range = selection.createRange().duplicate();
1691                range.moveStart('character', -val.length);
1692                e = range.text.length;
1693            } else {
1694                range = selection.createRange();
1695                var storedRange = range.duplicate();
1696                storedRange.moveToElementText(elem[0]);
1697                storedRange.setEndPoint('EndToEnd', range);
1698                s = storedRange.text.length - range.text.length;
1699                e = s + range.text.length;
1700            }
1701        } else {
1702            // ff, chrome, safari
1703            s = elem[0].selectionStart;
1704            e = elem[0].selectionEnd;
1705        }
1706        return {
1707            start: s,
1708            end: e
1709        };
1710    };
1711
1712    $.dnnAutocompleter.prototype.setValue = function (value) {
1713        if (this.options.useDelimiter) {
1714            // set the substring between the current delimiters
1715            var val = this.dom.$elem.val();
1716            var d = this.getDelimiterOffsets();
1717            var preVal = val.substring(0, d.start);
1718            var postVal = val.substring(d.end);
1719            value = preVal + value + postVal;
1720        }
1721        this.dom.$elem.val(value).blur();
1722    };
1723
1724    $.dnnAutocompleter.prototype.getValue = function () {
1725        var val = this.dom.$elem.val();
1726        if (this.options.useDelimiter) {
1727            var d = this.getDelimiterOffsets();
1728            return val.substring(d.start, d.end).trim();
1729        } else {
1730            return val;
1731        }
1732    };
1733
1734    $.dnnAutocompleter.prototype.getDelimiterOffsets = function () {
1735        var val = this.dom.$elem.val();
1736        if (this.options.useDelimiter) {
1737            var preCaretVal = val.substring(0, this.getCaret().start);
1738            var start = preCaretVal.lastIndexOf(this.options.delimiterChar) + 1;
1739            var postCaretVal = val.substring(this.getCaret().start);
1740            var end = postCaretVal.indexOf(this.options.delimiterChar);
1741            if (end == -1) end = val.length;
1742            end += this.getCaret().start;
1743        } else {
1744            start = 0;
1745            end = val.length;
1746        }
1747        return {
1748            start: start,
1749            end: end
1750        };
1751    };
1752})(jQuery);
1753
1754(function ($) {
1755    // dnn customized tags
1756    var delimiter = new Array();
1757    var tagsCallbacks = new Array();
1758    $.fn.dnnDoAutosize = function (o) {
1759        var minWidth = $(this).data('minwidth'),
1760            maxWidth = $(this).data('maxwidth'),
1761            val = '',
1762            input = $(this),
1763            testSubject = $('#' + $(this).data('tester_id'));
1764
1765        if (val === (val = input.val())) { return; }
1766
1767        // Enter new content into testSubject
1768        var escaped = val.replace(/&/g, '&amp;').replace(/\s/g, ' ').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1769        testSubject.html(escaped);
1770        // Calculate new width + whether to change
1771        var testerWidth = testSubject.width(),
1772            newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
1773            currentWidth = input.width(),
1774            isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
1775                                 || (newWidth > minWidth && newWidth < maxWidth);
1776
1777        // Animate width
1778        if (isValidWidthChange) {
1779            input.width(newWidth);
1780        }
1781    };
1782
1783    $.fn.dnnResetAutosize = function (options) {
1784	    var minWidth = $(this).data('minwidth') || options.minInputWidth || $(this).width(),
1785	        maxWidth = $(this).data('maxwidth') || options.maxInputWidth || ($(this).closest('.dnnTagsInput').width() - options.inputPadding),
1786	        $input = $(this);
1787
1788		var left = 0;
1789		var $lastSpan = $(this).closest('.dnnTagsInput').find('> span').last();
1790		if ($lastSpan.length > 0) {
1791			left = $lastSpan.offset().left - $lastSpan.parent().offset().left + $lastSpan.outerWidth();
1792		}
1793		var availableWidth = maxWidth - left;
1794	    if (availableWidth < parseInt(minWidth)) {
1795		    availableWidth = maxWidth;
1796	    }
1797
1798        $input.css('width', availableWidth);
1799    };
1800
1801    $.fn.dnnAddTag = function (value, options) {
1802        options = jQuery.extend({ focus: false, callback: true }, options);
1803        this.each(function () {
1804            var id = $(this).attr('id');
1805            var tagslist = $(this).val().split(delimiter[id]);
1806            if (tagslist[0] == '') {
1807                tagslist = new Array();
1808            }
1809			value = value.replace(/<.*?>/g, '');
1810            value = jQuery.trim(value);
1811            var skipTag;
1812            if (options.unique) {
1813                skipTag = $(this).dnnTagExist(value);
1814                if (skipTag == true) {
1815                    //Marks fake input as not_valid to let styling it
1816                    $('#' + id + '_tag').addClass('dnnTagsInvali
1816d');
1817                }
1818                else
1819                    $('#' + id + '_tag').removeClass('dnnTagsInvalid');
1820            } else {
1821                skipTag = false;
1822                $('#' + id + '_tag').removeClass('dnnTagsInvalid');
1823            }
1824
1825            if (value != '' && skipTag != true) {
1826                $('<span>').addClass('tag').append(
1827                    $('<span>').text(value).append('&nbsp;&nbsp;'),
1828                    $('<a aria-label="remove">', {
1829                        href: '#',
1830                        title: 'Removing tag'
1831                    }).click(function () {
1832                        return $('#' + id).dnnRemoveTag(escape(value));
1833                    })
1834                ).insertBefore('#' + id + '_addTag');
1835
1836                tagslist.push(value);
1837
1838                $('#' + id + '_tag').val('');
1839                if (options.focus) {
1840                    $('#' + id + '_tag').focus();
1841                } else {
1842                    $('#' + id + '_tag').blur();
1843                }
1844
1845                $.fn.dnnTagsInput.updateTagsField(this, tagslist);
1846                var f;
1847                if (options.callback && tagsCallbacks[id] && tagsCallbacks[id]['onAddTag']) {
1848                    f = tagsCallbacks[id]['onAddTag'];
1849                    f.call(this, value);
1850                }
1851                if (tagsCallbacks[id] && tagsCallbacks[id]['onChange']) {
1852                    var i = tagslist.length;
1853                    f = tagsCallbacks[id]['onChange'];
1854                    f.call(this, $(this), tagslist[i - 1]);
1855                }
1856            }
1857        });
1858        return false;
1859    };
1860
1861    $.fn.dnnRemoveTag = function (value) {
1862        value = unescape(value);
1863        this.each(function () {
1864            var id = $(this).attr('id');
1865            var old = $(this).val().split(delimiter[id]);
1866            $('#' + id + '_tagsinput .tag').remove();
1867            var str = '';
1868            for (var i = 0; i < old.length; i++) {
1869                if (old[i] != value) {
1870                    str = str + delimiter[id] + old[i];
1871                }
1872            }
1873            $.fn.dnnTagsInput.importTags(this, str);
1874            if (tagsCallbacks[id] && tagsCallbacks[id]['onRemoveTag']) {
1875                var f = tagsCallbacks[id]['onRemoveTag'];
1876                f.call(this, value);
1877            }
1878        });
1879
1880        return false;
1881    };
1882
1883    $.fn.dnnTagExist = function (val) {
1884        var id = $(this).attr('id'),
1885            tagslist = $(this).val().split(delimiter[id]);
1886        return (jQuery.inArray(val, tagslist) >= 0);
1887    };
1888
1889    $.fn.dnnImportTags = function (str) {
1890        var id = $(this).attr('id');
1891        $('#' + id + '_tagsinput .tag').remove();
1892        $.fn.dnnTagsInput.importTags(this, str);
1893    };
1894
1895    $.fn.dnnTagsInput = function (options) {
1896        var onError = null;
1897        var triggerOnError = function (handler) {
1898            if (!onError) {
1899                onError = setTimeout(function () {
1900                    onError = null;
1901                    if (handler) handler();
1902                }, 0);
1903            }
1904        };
1905        var settings = jQuery.extend({
1906            interactive: true,
1907            defaultText: 'Add a tag',
1908            minChars: 0,
1909            maxChars: 50,
1910            maxTags: 16,
1911            lessThanMinCharsErrorText: 'A tag cannot be less than {0} characters long',
1912            lessThanMinCharsErrorTitle: 'Tag Length Not Reached',
1913            moreThanMaxCharsErrorText: 'A tag cannot be more than {0} characters long',
1914            moreThanMaxCharsErrorTitle: 'Tag Length Exceeded',
1915            moreThanMaxTagsErrorText: 'A maximum of {0} tags can be attached here',
1916            moreThanMaxTagsErrorTitle: 'Tags limit exceeded',
1917            onErrorLessThanMinChars: function () { // can be customised by module dev
1918                $.dnnAlert({ text: String.format(settings.lessThanMinCharsErrorText, settings.minChars), title: settings.lessThanMinCharsErrorTitle });
1919            },
1920            onErrorMoreThanMaxChars: function () { // can be customised by module dev
1921                $.dnnAlert({ text: String.format(settings.moreThanMaxCharsErrorText, settings.maxChars), title: settings.moreThanMaxCharsErrorTitle });
1922            },
1923            onErrorMoreThanMaxTags: function () { // can be customised by module dev
1924                $.dnnAlert({ text: String.format(settings.moreThanMaxTagsErrorText, settings.maxTags), title: settings.moreThanMaxTagsErrorTitle });
1925            },
1926
1927            width: '45%',
1928            autocomplete: { selectFirst: false },
1929            'hide': true,
1930            'delimiter': ',',
1931            'unique': true,
1932            removeWithBackspace: true,
1933            placeholderColor: '#999',
1934            normalColor: '#666',
1935            autosize: true,
1936            comfortZone: 20,
1937            inputPadding: 6 * 2
1938
1939        }, options);
1940
1941        this.each(function () {
1942            var instance = $(this).data('dnnTagInput');
1943            if (instance) return this;
1944            if (settings.hide) {
1945                $(this).hide();
1946            }
1947            var id = $(this).attr('id');
1948            if (!id || delimiter[$(this).attr('id')]) {
1949                id = $(this).attr('id', 'tags' + new Date().getTime()).attr('id');
1950            }
1951            var data = jQuery.extend({
1952                pid: id,
1953                real_input: '#' + id,
1954                holder: '#' + id + '_tagsinput',
1955                input_wrapper: '#' + id + '_addTag',
1956                fake_input: '#' + id + '_tag'
1957            }, settings);
1958
1959            $(this).data('dnnTagInput', data);
1960
1961            delimiter[id] = data.delimiter;
1962
1963            if (settings.onAddTag || settings.onRemoveTag || settings.onChange) {
1964                tagsCallbacks[id] = new Array();
1965                tagsCallbacks[id]['onAddTag'] = settings.onAddTag;
1966                tagsCallbacks[id]['onRemoveTag'] = settings.onRemoveTag;
1967                tagsCallbacks[id]['onChange'] = settings.onChange;
1968            }
1969
1970            var markup = '<div id="' + id + '_tagsinput" class="dnnTagsInput">';
1971            markup += '<div id="' + id + '_addTag">';
1972
1973            if (settings.interactive) {
1974                markup += '<input id="' + id + '_tag" value="" data-default="' + settings.defaultText + '" autocomplete="off" aria-label="Search" />';
1975            }
1976
1977            markup += '</div>';
1978            markup = markup + '<div class="dnnTagsClear"></div></div>';
1979
1980            $(markup).insertAfter(this);
1981
1982            $(data.holder).css({
1983                'width': settings.width,
1984                'min-height': settings.height
1985            });
1986
1987            $(data.fake_input).attr("maxlength", settings.maxChars);
1988
1989            if ($(data.real_input).val() != '') {
1990                $.fn.dnnTagsInput.importTags($(data.real_input), $(data.real_input).val());
1991            }
1992            if (settings.interactive) {
1993                // placeholder stuff
1994                $(data.fake_input).dnnPlaceholder({
1995	                color: [settings.normalColor, settings.placeholderColor]
1996                });
1997
1998                $(data.fake_input).dnnResetAutosize(settings);
1999                $(data.holder).on('click', data, function (event) {
2000                    $(event.data.real_input).triggerHandler('focus');
2001                    $(event.data.fake_input).triggerHandler('focus');
2002                    return false;
2003                });
2004                if (settings.autocomplete_url != undefined) {
2005                    if ($.dnnAutocompleter !== undefined) {
2006                        if (settings.advanced && settings.advanced.length) {
2007                            settings.autocomplete.advanced = settings.advanced;
2008                        }
2009
2010                        $(data.fake_input).dnnAutocomplete(settings.autocomplete_url, settings.autocomplete);
2011                        $(data.fake_input).on('result', data, function (event, tag) {
2012                            if (tag) {
2013                                var tagslist = $(event.data.real_input).val().split(delimiter[id]);
2014                                if (tagslist[0] == '') {
2015                                    tagslist = new Array();
2016                                }
2017                                if (event.data.maxTags <= tagslist.length) {
2018                                    if (event.data.onErrorMoreThanMaxTags)
2019                                        triggerOnError(event.data.onErrorMoreThanMaxTags);
2020                                    $(data.fake_input).val('');
2021                                }
2022                                else
2023                                    $(event.data.real_input).dnnAddTag(tag, { focus: true, unique: (settings.unique) });
2024                            }
2025                        });
2026                    }
2027                } else {
2028                    // if a user tabs out of the field, create a new tag
2029                    // this is only available if autocomplete is not used.
2030                    $(data.fake_input).on('blur', data, function (event) {
2031                        var d = $(this).attr('data-default');
2032                        var tagslist = $(event.data.real_input).val().split(delimiter[id]);
2033                        if (tagslist[0] == '') {
2034                            tagslist = new Array();
2035                        }
2036                        if ($(event.data.fake_input).val() != '' && $(event.data.fake_input).val() != d) {
2037                            if (event.data.minChars > $(event.data.fake_input).val().length) {
2038                                if (event.data.onErrorLessThanMinChars)
2039                                    triggerOnError(event.data.onErrorLessThanMinChars);
2040                                $(data.fake_input).val('');
2041                            }
2042                            else if (event.data.maxChars < $(event.data.fake_input).val().length) {
2043                                if (event.data.onErrorMoreThanMaxChars)
2044                                    triggerOnError(event.data.onErrorMoreThanMaxChars);
2045                                $(data.fake_input).val('');
2046                            }
2047                            else if (event.data.maxTags <= tagslist.length) {
2048                                if (event.data.onErrorMoreThanMaxTags)
2049                                    triggerOnError(event.data.onErrorMoreThanMaxTags);
2050                                $(data.fake_input).val('');
2051                            }
2052                            else{
2053								var tags = $(event.data.fake_input).val().split(delimiter[id]);
2054								for(var i = 0; i < tags.length; i++){
2055									$(event.data.real_input).dnnAddTag(tags[i], { focus: true, unique: (settings.unique) });
2056								}
2057                            }
2058                            $(event.data.fake_input).dnnResetAutosize(sett
2058ings);
2059                        }
2060
2061                        return false;
2062                    });
2063
2064                }
2065
2066                function tagItems(data, event) {
2067                        var tagslist = $(event.data.real_input).val().split(delimiter[id]);
2068                        if (tagslist[0] == '') {
2069                            tagslist = new Array();
2070                        }
2071                        if (event.data.minChars > $(event.data.fake_input).val().length) {
2072                            if (event.data.onErrorLessThanMinChars)
2073                                triggerOnError(event.data.onErrorLessThanMinChars);
2074                            $(data.fake_input).val('');
2075                        }
2076                        else if (event.data.maxChars < $(event.data.fake_input).val().length) {
2077                            if (event.data.onErrorMoreThanMaxChars)
2078                                triggerOnError(event.data.onErrorMoreThanMaxChars);
2079                            $(data.fake_input).val('');
2080                        }
2081                        else if (event.data.maxTags <= tagslist.length) {
2082                            if (event.data.onErrorMoreThanMaxTags)
2083                                triggerOnError(event.data.onErrorMoreThanMaxTags);
2084                            $(data.fake_input).val('');
2085                        }
2086                        else {
2087                            var tags = $(event.data.fake_input).val().split(delimiter[id]);
2088                            for (var i = 0; i < tags.length; i++) {
2089                                $(event.data.real_input).dnnAddTag(tags[i], { focus: true, unique: (settings.unique) });
2090                            }
2091                        }
2092
2093                        $(event.data.fake_input).dnnResetAutosize(settings);
2094                        return false;
2095                }
2096
2097                var clickedOnAutoComplete = false;
2098
2099                $(document).mousedown(function (e) {
2100                    if ($(e.target).hasClass("dnn_acSelect") || $(e.target).parent().hasClass('dnn_acSelect')) {
2101                        clickedOnAutoComplete = true;
2102                    }
2103                });
2104
2105                var tagTooLongErrMsg = $('<span class="dnnFormError dnnFormMessage">' + String.format(settings.moreThanMaxCharsErrorText, settings.maxChars) + '</span>');
2106                // if user types a comma, create a new tag
2107                $(data.fake_input).on('keypress keydown blur', data, function (event) {
2108                    if ($(this).val() === "" || clickedOnAutoComplete) {
2109                        return;
2110                    }
2111                    var currValLength = $(this).val().length;
2112                    if ((currValLength >= settings.maxChars) && !(event.which == event.data.delimiter.charCodeAt(0) || event.which == 13 || event.which == 9)) {
2113                        tagTooLongErrMsg.insertAfter($(this)).show().delay(1500).fadeOut(1000);
2114                    }
2115                    if (event.which == event.data.delimiter.charCodeAt(0) || event.which == 13 || event.which == 9 || event.type == "blur") {
2116                        event.preventDefault();
2117                        if (!clickedOnAutoComplete) {
2118                            tagItems(data, event);
2119                        }
2120                        clickedOnAutoComplete = false;
2121                    } else if (event.data.autosize) {
2122                        $(event.data.fake_input).dnnDoAutosize(settings);
2123                    }
2124                    return true;
2125                });
2126                //Delete last tag on backspace
2127                data.removeWithBackspace && $(data.fake_input).on('keydown', function (event) {
2128                    if (event.keyCode == 8 && $(this).val() == '') {
2129                        event.preventDefault();
2130                        var lastTag = $(this).closest('.dnnTagsInput').find('.tag:last').text();
2131                        var lastTagId = $(this).attr('id').replace(/_tag$/, '');
2132                        lastTag = lastTag.replace(/[\s]+$/, '');
2133                        $('#' + lastTagId).dnnRemoveTag(escape(lastTag));
2134                        $(this).trigger('focus');
2135                    }
2136                });
2137                $(data.fake_input).blur();
2138
2139                //Removes the not_valid class when user changes the value of the fake input
2140                if (data.unique) {
2141                    $(data.fake_input).keydown(function (event) {
2142                        if (event.keyCode == 8 || String.fromCharCode(event.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/)) {
2143                            $(this).removeClass('dnnTagsInvalid');
2144                        }
2145                    });
2146                }
2147
2148            } // if settings.interactive
2149            return this;
2150        });
2151        return this;
2152    };
2153
2154    $.fn.dnnTagsInput.updateTagsField = function (obj, tagslist) {
2155        var id = $(obj).attr('id');
2156        $(obj).val(tagslist.join(delimiter[id]));
2157    };
2158
2159    $.fn.dnnTagsInput.importTags = function (obj, val) {
2160        $(obj).val('');
2161        var id = $(obj).attr('id');
2162        var tags = val.split(delimiter[id]);
2163        for (var i = 0; i < tags.length; i++) {
2164            $(obj).dnnAddTag(tags[i], { focus: false, callback: false });
2165        }
2166        if (tagsCallbacks[id] && tagsCallbacks[id]['onChange']) {
2167            var f = tagsCallbacks[id]['onChange'];
2168            f.call(obj, obj, tags[i]);
2169        }
2170    };
2171
2172    $.fn.dnnPlaceholder = function (options) {
2173	    options = $.extend({}, {
2174	    	cssClass: 'dnnPlaceholder',
2175			color: []
2176	    }, options);
2177
2178	    this.each(function () {
2179		    var $this = $(this);
2180			var instance = $this.data('dnnPlaceHolder');
2181			if (instance) return true;
2182			$this.data('dnnPlaceHolder', true);
2183
2184			var placeholderSupported = ('placeholder' in $this[0]);
2185            if (placeholderSupported)
2186                $this.attr('placeholder', $this.attr('data-default'));
2187            else {
2188            	var $fakeInput = $('<input type="text" />')
2189					.attr('class', $this.attr('class'))
2190					.attr('style', $this.attr('style'))
2191					.val($this.attr('data-default'));
2192
2193            	$this.hide().after($fakeInput);
2194				if (options.color.length === 2) {
2195					$fakeInput.css('color', options.color[1]);
2196					$this.css('color', options.color[0]);
2197				} else {
2198					$fakeInput.addClass(options.cssClass);
2199				}
2200
2201
2202	            $fakeInput.on('focus', function(event) {
2203		            $fakeInput.hide();
2204		            $this.show().focus();
2205	            });
2206
2207				$this.on('blur', function (event) {
2208					var d = $this.attr('data-default');
2209					if ($this.val() === '') {
2210						$this.hide();
2211						$fakeInput.show();
2212					}
2213				});
2214
2215				var events = $._data(this, 'events')['blur'];
2216				var first = events.pop();
2217				events.splice(0, 0, first);
2218            }
2219
2220		    return true;
2221	    });
2222
2223		return this;
2224	};
2225})(jQuery);
2226
2227(function ($) {
2228    // dnnForm customised client side validation
2229    $.fn.toggleErrorMessage = function (options) {
2230        var defaultOptions = {
2231            errorMessage: "Error message",
2232            errorCls: "dnnFormError",
2233            show: true,
2234            removeErrorMessage: true
2235        };
2236
2237        options = $.extend(defaultOptions, options);
2238
2239        return this.each(function () {
2240            var dnnFormItem = $(this).closest('.dnnFormItem');
2241            if (options.show) {
2242                var errorSpan = dnnFormItem.find('span.dnnFormMessage.' + options.errorCls);
2243                if (errorSpan.length) {
2244                    errorSpan.html(options.errorMessage);
2245                } else {
2246                    errorSpan = $('<span class="dnnFormMessage ' + options.errorCls + '">' + options.errorMessage + '</span>');
2247                    dnnFormItem.append(errorSpan);
2248                }
2249
2250                if (this.tagName.toLowerCase() == 'div') {
2251                    // customised controls
2252                    if ($(this).hasClass('RadComboBox')) {
2253                        // RadComboBox
2254                        $(this).addClass('dnnError');
2255                    }
2256                }
2257                else {
2258                    if ($(this).parent().hasClass('RadPicker')) {
2259                        // RadDate Picker
2260                        $(this).parent().find('input.riTextBox').css('border', '1px solid red');
2261                    }
2262                    else if ($(this).hasClass('dnnSpinnerInput')) {
2263                        // Spinner
2264                        $(this).parent().css('border', '1px solid red');
2265                    }
2266                    else {
2267                        // normal ctrl
2268                        $(this).css('border', '1px solid red');
2269                    }
2270                }
2271            }
2272            else {
2273                if (options.removeErrorMessage)
2274                    dnnFormItem.find('span.' + options.errorCls).remove();
2275                else
2276                    dnnFormItem.find('span.' + options.errorCls).hide();
2277
2278                if (this.tagName.toLowerCase() == 'div') {
2279                    // customised controls
2280                    if ($(this).hasClass('RadComboBox')) {
2281                        // RadComboBox
2282                        $(this).removeClass('dnnError');
2283
2284                    }
2285                }
2286                else {
2287                    if ($(this).hasClass('dnnSpinnerInput')) {
2288                        // Spinner
2289                        $(this).parent().css('border', '1px solid #ccc');
2290                    }
2291                    else {
2292                        // normal ctrl
2293                        $(this).css('border', '1px solid #ccc');
2294                    }
2295                }
2296            }
2297        });
2298    };
2299    $.fn.dnnFormSubmit = function (options) {
2300        var defaultOptions = {
2301            validates: []
2302        };
2303
2304        options = $.extend(defaultOptions, options);
2305
2306        return this.each(function () {
2307            $(this).click(function () {
2308                var formValidate = true;
2309                for (var i = 0; i < options.validates.length; i++) {
2310                    var ele = $('#' + options.validates[i].ele);
2311                    var func = options.validates[i].func;
2312                    if (ele.length) {
2313                        var eleVal = ele.val();
2314                        var eleError = func.call(ele.get(0), eleVal);
2315                        if (eleError) {
2316                            ele.toggleErrorMessage({ errorMessage: eleError, show: true });
2317                            formValidate = false;
2318                        }
2319                        else {
2320                            ele.toggleErrorMessage({ show: false });
2321                        }
2322
2323                        //ele focus then remove error info
2324                        var hideErrorInfo = function () {
2325                            $(this).toggleErrorMessage({ show: false });
2326                        };
2327
2328                        ele.off('focus', hideErrorInfo).on('focus', hideErrorInfo);
2329                    }
2330                }
2331
2332                return formValidate;
2333            });
2334        });
2335    };
2336
2337    // fix telerik custom datepicker popup arrow position       
2338    $.dnnRadPickerHack = function () {
2339        //when click this icon, hide error info
2340        var hideErrorInfo = function () {
2341            $(this).toggleErrorMessage({ show: false, removeErrorMessage: false });
2342        };
2343        var dnnRadPickerPopupFix = function () {
2344            if ($.support.cssFloat) {
2345                var id = $(this).attr('id');
2346                var popupId = id.replace('popupButton', 'calendar_wrapper');
2347                var popupElement = $('#' + popupId);
2348                var wrapperId = id.replace('popupButton', 'wrapper');
2349                var wrapperElement = $('#' + wrapperId);
2350
2351                var popupElementTop = popupElement.parent().position().top;
2352                var wrapperElementTop = wrapperElement.offset().top;
2353                var popupTbl = popupElement.find('.RadCalendar_Default');
2354                var nextEle = popupTbl.next();
2355                if (nextEle.hasClass('RadCalendar_Default_PopupArrow_Down') || nextEle.hasClass('RadCalendar_Default_PopupArrow_Up'))
2356                    nextEle.remove();
2357
2358                if (popupElementTop < wrapperElementTop) { // popup above the calendar ctrl, so show arrow down
2359                    popupTbl.after('<div class="RadCalendar_Default_PopupArrow_Down"></div>');
2360                }
2361                else { // popup below the calendar ctrl, so show arrow up
2362                    popupTbl.after('<div class="RadCalendar_Default_PopupArrow_Up"></div>');
2363                }
2364            }
2365
2366            $(this).toggleErrorMessage({ show: false, removeErrorMessage: false });
2367        };
2368        $('.RadPicker_Default a.rcCalPopup').off('click', dnnRadPickerPopupFix).on('click', dnnRadPickerPopupFix);
2369        $('.RadPicker_Default .riTextBox').off('focus', hideErrorInfo).on('focus', hideErrorInfo);
2370    };
2371
2372    // remove combobox inline style
2373    $.dnnComboBoxLoaded = function (sender) {
2374        // Telerik has been removed - this function is kept for compatibility
2375    };
2376
2377    //fix combobox hide error info
2378    $.dnnComboBoxHack = function (sender) {
2379        $(('#' + sender._clientStateFieldID).replace('_ClientState', '')).toggleErrorMessage({ show: false, removeErrorMessage: false });
2380    };
2381
2382    //fix combobox scroll
2383    $.dnnComboBoxScroll = function (sender) {
2384        if ($.support.cssFloat) {
2385            var container = $(('#' + sender._clientStateFieldID + ' .rcbScroll').replace('ClientState', 'DropDown'));
2386            if (container.data('scrollPane')) {
2387                container.data('scrollPane').data('jsp').reinitialise();
2388            } else {
2389                container.data('scrollPane', container.jScrollPane());
2390            }
2391        }
2392    };
2393
2394    $.dnnComboBoxItemRequested = function (sender) {
2395        setTimeout(function() {
2396            var container = $(('#' + sender._clientStateFieldID + ' .rcbScroll').replace('ClientState', 'DropDown'));
2397            if (container.data('scrollPane')) {
2398                container.data('scrollPane').data('jsp').reinitialise();
2399            }
2400        }, 0);
2401    };
2402
2403    // fix grid issues 
2404    $.dnnGridCreated = function (sender) {
2405        var clientId = sender.ClientID;
2406        var $grid = $('#' + clientId);
2407        $('input.rgSortDesc, input.rgSortAsc', $grid).click(function () {
2408            var href = $(this).parent().find('a').get(0).href;
2409            window.location = href;
2410            return false;
2411        });
2412
2413        if ($grid.hasClass('dnnTooltipGrid')) {
2414            $grid.dnnHelperTipDestroy();
2415            $('.rgRow, .rgAltRow', $grid).each(function () {
2416                var info = "Here is some text will show up and explian more about this information";
2417                $(this).dnnHelperTip({ helpContent: info, holderId: clientId });
2418            });
2419        }
2420
2421        var grid = $find(clientId);
2422
2423        // while using customised checkbox - remove onclick event then attach onchange
2424        var headerCheck = $('.rgCheck', $grid);
2425        if (headerCheck.length) {
2426            headerCheck.each(function () {
2427                var checkbox = $(this).find('input[type="checkbox"]').get(0);
2428                var onclick = checkbox.onclick;
2429                checkbox.onchange = onclick;
2430                checkbox.onclick = null;
2431            });
2432
2433            // when use customised scrollbar and customised checkbox, the row cannot be correctly selected
2434            $('.rgDataDiv input[type="checkbox"]', $grid).change(function () {
2435                var masterTable = grid.get_masterTableView();
2436                var rowIndex = $(this).closest('tr').get(0).rowIndex;
2437                var checked = this.checked;
2438                if (checked)
2439                    masterTable.selectItem(rowIndex);
2440                else
2441                    masterTable.deselectItem(rowIndex);
2442            });
2443        }
2444
2445        // initialize dnnGrid customised scrollbar
2446        $('.rgDataDiv').each(function () {
2447            var $this = $(this);
2448            var ele = $this.get(0);
2449            ele.scrollPane = $this.jScrollPane();
2450            var api = ele.scrollPane.data('jsp');
2451            var throttleTimeout;
2452            $(window).on(
2453                'resize',
2454                function () {
2455                    if (!$.support.cssFloat) {
2456                        if (throttleTimeout) {
2457                            clearTimeout(throttleTimeout);
2458                            throttleTimeout = null;
2459                        }
2460                        throttleTimeout = setTimeout(
2461                            function () {
2462                                api.reinitialise();
2463                                throttleTimeout = null;
2464                            },
2465                            50
2466                        );
2467                    } else {
2468                        api.reinitialise();
2469                    }
2470                }
2471            );
2472            if (window.__rgDataDivScrollTopPersistArray && window.__rgDataDivScrollTopPersistArray.length) {
2473                var y = window.__rgDataDivScrollTopPersistArray.pop();
2474                api.scrollToY(y);
2475            }
2476        });
2477    };
2478})(jQuery);
2479
2480(function ($) {
2481    var types = ['DOMMouseScroll', 'mousewheel'];
2482    if ($.event.fixHooks) {
2483        for (var i = types.length; i;) {
2484            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
2485        }
2486    }
2487    $.event.special.mousewheel = {
2488        setup: function () {
2489            if (this.addEventListener) {
2490                for (var i = types.length; i;) {
2491                    this.addEventListener(types[--i], handler, false);
2492                }
2493            } else {
2494                this.onmousewheel = handler;
2495            }
2496        },
2497
2498        teardown: function () {
2499            if (this.removeEventListener) {
2500                for (var i = types.length; i;) {
2501                    this.removeEventListener(types[--i], handler, false);
2502                }
2503            } else {
2504                this.onmousewheel = null;
2505            }
2506        }
2507    };
2508
2509    $.fn.extend({
2510        mousewheel: function (fn) {
2511            return fn ? this.on("mousewheel", fn) : this.trigger("mousewheel");
2512        },
2513
2514        unmousewheel: function (fn) {
2515            return this.off("mousewheel", fn);
2516        }
2517    });
2518
2519    function handler(event) {
2520        var orgEvent = event || window.event,
2521            args = [].slice.call(arguments, 1),
2522            delta = 0,
2523            deltaX = 0,
2524            deltaY = 0;
2525        event = $.event.fix(orgEvent);
2526        event.type = "mousewheel";
2527
2528        // Old school scrollwheel delta
2529        if (orgEvent.wheelDelta) { delta = orgEvent.wheelDelta / 120; }
2530        if (orgEvent.detail) { delta = -orgEvent.detail / 3; }
2531
2532        // New school multidimensional scroll (touchpads) deltas
2533        deltaY = delta;
2534
2535        // Gecko
2536        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
2537            deltaY = 0;
2538            deltaX = -1 * delta;
2539        }
2540
2541        // Webkit
2542        if (orgEvent.wheelDeltaY !== undefined) { deltaY = orgEvent.wheelDeltaY / 120; }
2543        if (orgEvent.wheelDeltaX !== undefined) { deltaX = -1 * orgEvent.wheelDeltaX / 120; }
2544
2545        // Add event and delta to the front of the arguments
2546        args.unshift(event, delta, deltaX, deltaY);
2547        return ($.event.dispatch || $.event.handle).apply(this, args);
2548    }
2549
2550})(jQuery);
2551
2552(function ($) {
2553    $.fn.dnnFileInput = function (options) {
2554        var opts = $.extend({}, $.fn.dnnFileInput.defaultOptions, options);
2555
2556        return this.each(function () {
2557            var $ctrl = $(this);
2558            if ($ctrl.hasClass('normalFileUpload')) return;
2559
2560            if (this.wrapper)
2561                return;
2562
2563            //ignore decoration for elements in rad control.
2564            if ($ctrl.parents().hasClass("RadUpload"))
2565                return;
2566
2567            // if this.wrapper is undefined, then we check if parent node is a wrapper
2568            if (this.parentNode && this.parentNode.tagName.toLowerCase() == 'span' && $ctrl.parent().hasClass('dnnInputFileWrapper')) {
2569                return;
2570            }
2571
2572            this.wrapper = $("<span class='dnnInputFileWrapper " + opts.buttonClass + "'></span>");
2573            var text = $ctrl.data('text');
2574            text = text || 'Choose File';
2575            this.wrapper.text(text);
2576            $ctrl.wrap(this.wrapper);
2577            $ctrl.data("wrapper", $ctrl.parent());
2578
2579            if (opts.showSelectedFileNameAsButtonText) {
2580                $ctrl.change(function () {
2581                    var val = $(this).val();
2582                    if (val != '') {
2583                        var lastIdx = val.lastIndexOf('\\') + 1;
2584                        val = val.substring(lastIdx, val.length);
2585                    } else {
2586                        val = text;
2587                    }
2588                    $(this).data("wrapper").get(0).childNodes[0].nodeValue = val;
2589                });
2590            }
2591        });
2592    };
2593
2594    $.fn.dnnFileInput.defaultOptions = {
2595        buttonClass: 'dnnSecondaryAction',
2596        showSelectedFileNameAsButtonText: true
2597    };
2598})(jQuery);
2599
2600(function ($) {
2601    var supportAjaxUpload = function () {
2602        var xhr = new XMLHttpRequest;
2603        return !!(xhr && ('upload' in xhr) && ('onprogress' in xhr.upload));
2604    };
2605
2606    $.fn.dnnFileUpload = function (settings) {
2607        return this.each(function () {
2608            // set scope and settings, service
2609            var scope = $(this).attr('id');
2610            window.dnn.dnnFileUpload.setSettings(scope, settings);
2611            var service = $.dnnSF();
2612
2613            // hide progress
2614            $('#' + settings.progressBarId).parent().hide();
2615            // detect draggable support or not
2616            var droppableSpan = $('#' + settings.dropZoneId + '>span');
2617            if ('draggable' in document.createElement('span')) {
2618                droppableSpan.show();
2619            }
2620            else {
2621                droppableSpan.hide();
2622            }
2623
2624            // set file upload
2625            var url = service.getServiceRoot('internalservices') + 'fileupload/postfile';
2626            if (!supportAjaxUpload()) {
2627                var antiForgeryToken = $('input[name="__RequestVerificationToken"]').val();
2628                url += '?__RequestVerificationToken=' + antiForgeryToken;
2629            }
2630
2631            $('#' + scope + ' input[type="file"]').fileupload({
2632                url: url,
2633                beforeSend: service.setModuleHeaders,
2634                dropZone: $('#' + settings.dropZoneId),
2635                pasteZone: null,
2636                replaceFileInput: false,
2637                submit: function (e, data) {
2638                    data.formData = { folder: settings.folder, filter: settings.fileFilter, overwrite: 'true' };
2639                    return true;
2640                },
2641                progressall: function (e, data) {
2642                    var progress = parseInt(data.loaded / data.total * 100, 10);
2643                    if (progress < 100) {
2644                        $('#' + settings.progressBarId).parent().show();
2645                        $('#' + settings.progressBarId + '>div').css('width', progress + '%');
2646                    }
2647                    else
2648                        $('#' + settings.progressBarId).parent().hide();
2649                },
2650                done: function (e, data) {
2651                    $('#' + settings.progressBarId).parent().hide();
2652                    var img = new Image();
2653                    $(img).on('load', function () {
2654                        $('#' + settings.dropZoneId + ' img').remove();
2655                        $(img).css({ 'max-width': 180, 'max-height': 150 }).insertBefore($('#' + settings.dropZoneId + ' span'));
2656                    });
2657                    var src;
2658                    if (data.dataType && typeof(data.result) == "object" && data.result.length) {
2659                        data.result = JSON.parse(data.result.text());
2660                    } else {
2661                        data.result = JSON.parse(data.result);
2662                    }
2663                    var testContent = $('<pre>' + data.result.FilePath + '</pre>');
2664                    if (testContent.length) {
2665                        src = testContent.text();
2666                    }
2667                    else
2668                        src = data.result;
2669
2670                    if (src && $.trim(src)) {
2671                        var profileImagePath = dnn.getVar("sf_siteRoot", "/") + 'DnnImageHandler.ashx?mode=securefile&fileId=' + data.result.FileId + '&MaxWidth=180&MaxHeight=150';
2672                        img.src = profileImagePath;
2673                        
2674                        var fileName = data.result.FilePath.replace('\\', '/');
2675                        if (fileName.indexOf('/') > -1) {
2676                            fileName = fileName.split('/')[fileName.split('/').length - 1];
2677                        }
2678                        if (fileName.indexOf('?') > -1) {
2679                            fileName = fileName.split('?')[0];
2680                        }
2681                        
2682                        dnn[settings.filesComboId].refresh(dnn[settings.foldersComboId].selectedItem().key);
2683                        dnn[settings.filesComboId].selectedItem({ key: data.result.FileId, value: fileName});
2684                    }
2685                },
2686                fail: function (e, data) {
2687                    $('#' + settings.progressBarId).parent().hide();
2688                    var resp = JSON.parse(data.jqXHR.responseText);
2689                    alert(resp.Message);
2690                }
2691            });
2692
2693            $('#' + scope + ' input[name=uploadFileButton]').click(function() {
2694                var instance = dnn[settings.fileUploadId];
2695                
2696                var options = instance.options;
2697                if (dnn[settings.foldersComboId].selectedItem() != null) {
2698                    instance.options.folderPicker.initialState.selectedItem = dnn[settings.foldersComboId].selectedItem();
2699                    instance.options.folderPath = window.dnn.dnnFileUpload.getSelectedPath(dnn[settings.foldersComboId]);
2700                }
2701
2702                instance.show(options);
2703                
2704                window.dnn.dnnFileUpload.updateExpandPath(dnn[settings.foldersComboId], instance._panel._folderPicker.id());
2705                
2706                instance._panel.$element.on("onfileuploadcomplete", function (event, data) {
2707                    if (typeof data == "string") {
2708						// for modern browsers
2709                        data = JSON.parse(data);
2710                    }else{
2711						// for IE8-9						
2712						var b = data[0];
2713						data = JSON.parse(b.body.innerText);
2714					}
2715                    if (data && data.fileId) {
2716                        var folderPicker = instance._panel._folderPicker;
2717                        dnn[settings.foldersComboId].selectedItem(folderPicker.selectedItem());
2718                        window.dnn.dnnFileUpload.Folders_Changed(dnn[settings.foldersComboId].selectedItem(), dnn[settings.foldersComboId].$element);
2719                        window.dnn.dnnFileUpload.updateExpandPath(folderPicker, settings.foldersComboId);
2720                        
2721                        dnn[settings.filesComboId].refresh(dnn[settings.foldersComboId].selectedItem().key);
2722                        dnn[settings.filesComboId].selectedItem({ key: data.fileId.toString(), value: data.fileName });
2723                        window.dnn.dnnFileUpload.Files_Changed(dnn[settings.filesComboId].selectedItem(), dnn[settings.filesComboId].$element);
2724                    }
2725                });
2726            });
2727
2728            // set initial thumb image
2729            setTimeout(function () {
2730                dnn[settings.filesComboId].options.services.parameters.parentId = settings.selectedFolderId;
2731                var filesCombo = dnn[settings.filesComboId];
2732                var selectedFileId = filesCombo.selectedItem() ? filesCombo.selectedItem().key : null;                
2733             	var fileId  = selectedFileId ? parseInt(selectedFileId) : 0;
2734                if (fileId > 0) {
2735                    var maxWidth = 180, maxHeight = 150;
2736                    var profileImagePath = dnn.getVar("sf_siteRoot", "/") + 'DnnImageHandler.ashx?mode=securefile&fileId=' + fileId + '&MaxWidth=' + maxWidth + '&MaxHeight=' + maxHeight;
2737                    var img = new Image();
2738
2739                    $(img).on('load', function () {
2740                        $('#' + settings.dropZoneId + ' img').remove();
2741                        $(img).css({ 'max-width': maxWidth, 'max-height': maxHeight }).insertBefore($('#' + settings.dropZoneId + ' span'));
2742                    });
2743                    img.src = profileImagePath;        
2744                }
2745            }, 500);
2746        });
2747    };
2748
2749    if (typeof window.dnn === 'undefined') window.dnn = {};
2750    window.dnn.dnnFileUpload = window.dnn.dnnFileUpload || {};
2751    window.dnn.dnnFileUpload.settings = {};
2752    window.dnn.dnnFileUpload.setSettings = function (scope, settings) {
2753        window.dnn.dnnFileUpload.settings[scope] = settings;
2754    };
2755    window.dnn.dnnFileUpload.getSettings = function (sender) {
2756        var scope = sender.closest('.dnnFileUploadScope').attr('id');
2757        return window.dnn.dnnFileUpload.settings[scope];
2758    };
2759    window.dnn.dnnFileUpload.Folders_Changed = function (node, sender) {
2760        var settings = window.dnn.dnnFileUpload.getSettings(sender);
2761        if (!settings) return false;
2762
2763        if (node) {
2764            //get the selected folder path
2765            var selectedPathArray = dnn[settings.foldersComboId].selectedPath();
2766            if (selectedPathArray.length === 0 && settings.folder) {
2767                return settings.folder;
2768            }
2769            var selectedPath = "";
2770            if (selectedPathArray.length > 1) {
2771                for (var i = 1, size = selectedPathArray.length; i < size; i++) {
2772                    selectedPath += selectedPathArray[i].name + "/";
2773                }
2774            } 
2775            settings.folder = selectedPath;
2776
2777            dnn[settings.filesComboId].refresh(node.key);
2778            dnn[settings.filesComboId].selectedItem(null);
2779            window.dnn.dnnFileUpload.Files_Changed({ key: null }, $('#' + settings.filesComboId));
2780        }
2781    };
2782    window.dnn.dnnFileUpload.Files_Changed = function (node, sender) {
2783        var settings = window.dnn.dnnFileUpload.getSettings(sender);
2784        if (!settings) return;
2785
2786        if (node) {
2787            var fileId = node.key;
2788            if (fileId) {
2789                var maxWidth = 180, maxHeight = 150;
2790                var profileImagePath = dnn.getVar("sf_siteRoot", "/") + 'DnnImageHandler.ashx?mode=securefile&fileId=' + fileId + '&MaxWidth=' + maxWidth + '&MaxHeight=' + maxHeight;
2791                var img = new Image();
2792
2793                $(img).on('load', function () {
2794                    $('#' + settings.dropZoneId + ' img').remove();
2795                    $(img).css({ 'max-width': maxWidth, 'max-height': maxHeight }).insertBefore($('#' + settings.dropZoneId + ' span'));
2796                });
2797                img.src = profileImagePath;        
2798            }
2799            else
2800                $('#' + settings.dropZoneId + ' img').remove();
2801        }
2802    };
2803    window.dnn.dnnFileUpload.updateExpandPath = function(dropDownList, targetId) {
2804        //set expand path
2805        var selectedPaths = dropDownList.selectedPath();
2806        var expandPath = "";
2807        if (selectedPaths.length == 0) { //which means the tree view hasn't opened.
2808            expandPath = dnn.getVar(dropDownList.id() + '_expandPath');
2809        }
2810        else if (selectedPaths.length > 1) {
2811            for (var i = 0; i < selectedPaths.length - 1; i++) {
2812                if (expandPath == "") {
2813                    expandPath = selectedPaths[i].id;
2814                } else {
2815                    expandPath = expandPath + "," + selectedPaths[i].id;
2816                }
2817            }
2818        }
2819        
2820        if (expandPath != "") {
2821            dnn.setVar(targetId + '_expandPath', expandPath);
2822        }
2823    };
2824    window.dnn.dnnFileUpload.getSelectedPath = function(dropDownList) {
2825        var selectedPathArray = dropDownList.selectedPath();
2826        var settings = window.dnn.dnnFileUpload.getSettings(dropDownList.$element);
2827        if (selectedPathArray.length === 0 && settings.folder) {
2828            return settings.folder;
2829        }
2830        var selectedPath = "";
2831        if (selectedPathArray.length > 1) {
2832            for (var i = 1, size = selectedPathArray.length; i < size; i++) {
2833                selectedPath += selectedPathArray[i].name + "/";
2834            }
2835        }
2836        return selectedPath;
2837    };
2838})(jQuery);
2839
2840(function ($) {
2841    /* BELOW jscrollPane code */
2842    $.fn.jScrollPane = function (settings) {
2843        // JScrollPane "class" - public methods are available through $('selector').data('jsp')
2844        function JScrollPane(elem, s) {
2845            var settings, jsp = this, pane, paneWidth, paneHeight, container, contentWidth, contentHeight,
2846				percentInViewH, percentInViewV, isScrollableV, isScrollableH, verticalDrag, dragMaxY,
2847				verticalDragPosition, horizontalDrag, dragMaxX, horizontalDragPosition,
2848				verticalBar, verticalTrack, scrollbarWidth, verticalTrackHeight, verticalDragHeight, arrowUp, arrowDown,
2849				horizontalBar, horizontalTrack, horizontalTrackWidth, horizontalDragWidth, arrowLeft, arrowRight,
2850				reinitialiseInterval, originalPadding, originalPaddingTotalWidth, previousContentWidth,
2851				wasAtTop = true, wasAtLeft = true, wasAtBottom = false, wasAtRight = false,
2852				originalElement = elem.clone(false, false).empty(),
2853				mwEvent = $.fn.mwheelIntent ? 'mwheelIntent.jsp' : 'mousewheel.jsp';
2854
2855            originalPadding = elem.css('paddingTop') + ' ' +
2856								elem.css('paddingRight') + ' ' +
2857								elem.css('paddingBottom') + ' ' +
2858								elem.css('paddingLeft');
2859            originalPaddingTotalWidth = (parseInt(elem.css('paddingLeft'), 10) || 0) +
2860										(parseInt(elem.css('paddingRight'), 10) || 0);
2861
2862            function initialise(s) {
2863
2864                var /*firstChild, lastChild, */isMaintainingPositon, lastContentX, lastContentY,
2865						hasContainingSpaceChanged, originalScrollTop, originalScrollLeft,
2866						maintainAtBottom = false, maintainAtRight = false;
2867
2868                settings = s;
2869
2870                if (pane === undefined) {
2871                    originalScrollTop = elem.scrollTop();
2872                    originalScrollLeft = elem.scrollLeft();
2873
2874                    elem.css(
2875						{
2876						    overflow: 'hidden',
2877						    padding: 0
2878						}
2879					);
2880                    // TODO: Deal with where width/ height is 0 as it probably means the element is hidden and we should
2881                    // come back to it later and check once it is unhidden...
2882                    paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
2883                    paneHeight = elem.innerHeight();
2884
2885                    elem.width(paneWidth);
2886
2887                    pane = $('<div class="jspPane" />').css('padding', originalPadding).append(elem.children());
2888                    container = $('<div class="jspContainer" />')
2889						.css({
2890						    'width': paneWidth + 'px',
2891						    'height': paneHeight + 'px'
2892						}
2893					).append(pane).appendTo(elem);
2894
2895                    /*
2896					// Move any margins from the first and last children up to the container so they can still
2897					// collapse with neighbouring elements as they would before jScrollPane 
2898					firstChild = pane.find(':first-child');
2899					lastChild = pane.find(':last-child');
2900					elem.css(
2901						{
2902							'margin-top': firstChild.css('margin-top'),
2903							'margin-bottom': lastChild.css('margin-bottom')
2904						}
2905					);
2906					firstChild.css('margin-top', 0);
2907					lastChild.css('margin-bottom', 0);
2908					*/
2909                } else {
2910                    elem.css('width', '');
2911
2912                    maintainAtBottom = settings.stickToBottom && isCloseToBottom();
2913                    maintainAtRight = settings.stickToRight && isCloseToRight();
2914
2915                    hasContainingSpaceChanged = elem.innerWidth() + originalPaddingTotalWidth != paneWidth || elem.outerHeight() != paneHeight;
2916
2917                    if (hasContainingSpaceChanged) {
2918                        paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
2919                        paneHeight = elem.innerHeight();
2920                        container.css({
2921                            width: paneWidth + 'px',
2922                            height: paneHeight + 'px'
2923                        });
2924                    }
2925
2926                    // If nothing changed since last check...
2927                    if (!hasContainingSpaceChanged && previousContentWidth == contentWidth && pane.outerHeight() == contentHeight) {
2928                        elem.width(paneWidth);
2929                        return;
2930                    }
2931                    previousContentWidth = contentWidth;
2932
2933                    pane.css('width', '');
2934                    elem.width(paneWidth);
2935
2936                    container.find('>.jspVerticalBar,>.jspHorizontalBar').remove().end();
2937                }
2938
2939                pane.css('overflow', 'auto');
2940                if (s.contentWidth) {
2941                    contentWidth = s.contentWidth;
2942                } else {
2943                    contentWidth = pane[0].scrollWidth;
2944                }
2945                contentHeight = pane[0].scrollHeight;
2946                pane.css('overflow', '');
2947
2948                percentInViewH = contentWidth / paneWidth;
2949                percentInViewV = contentHeight / paneHeight;
2950                isScrollableV = percentInViewV > 1;
2951
2952                isScrollableH = percentInViewH > 1;
2953
2954                if (!(isScrollableH || isScrollableV)) {
2955                    elem.removeClass('jspScrollable');
2956                    pane.css({
2957                        top: 0,
2958                        width: container.width() - originalPaddingTotalWidth
2959                    });
2960                    removeMousewheel();
2961                    removeFocusHandler();
2962                    removeKeyboardNav();
2963                    removeClickOnTrack();
2964                } else {
2965                    elem.addClass('jspScrollable');
2966
2967                    isMaintainingPositon = settings.maintainPosition && (verticalDragPosition || horizontalDragPosition);
2968                    if (isMaintainingPositon) {
2969                        lastContentX = contentPositionX();
2970                        lastContentY = contentPositionY();
2971                    }
2972
2973                    initialiseVerticalScroll();
2974                    initialiseHorizontalScroll();
2975                    resizeScrollbars();
2976
2977                    if (isMaintainingPositon) {
2978                        scrollToX(maintainAtRight ? (contentWidth - paneWidth) : lastContentX, false);
2979                        scrollToY(maintainAtBottom ? (contentHeight - paneHeight) : lastContentY, false);
2980                    }
2981
2982                    initFocusHandler();
2983                    initMousewheel();
2984                    initTouch();
2985
2986                    if (settings.enableKeyboardNavigation) {
2987                        initKeyboardNav();
2988                    }
2989                    if (settings.clickOnTrack) {
2990                        initClickOnTrack();
2991                    }
2992
2993                    observeHash();
2994                    if (settings.hijackInternalLinks) {
2995                        hijackInternalLinks();
2996                    }
2997                }
2998
2999                if (settings.autoReinitialise && !reinitialiseInterval) {
3000                    reinitialiseInterval = setInterval(
3001						function () {
3002						    initialise(settings);
3003						},
3004						settings.autoReinitialiseDelay
3005					);
3006                } else if (!settings.autoReinitialise && reinitialiseInterval) {
3007                    clearInterval(reinitialiseInterval);
3008                }
3009
3010                originalScrollTop && elem.scrollTop(0) && scrollToY(originalScrollTop, false);
3011                originalScrollLeft && elem.scrollLeft(0) && scrollToX(originalScrollLeft, false);
3012
3013                elem.trigger('jsp-initialised', [isScrollableH || isScrollableV]);
3014            }
3015
3016            function initialiseVerticalScroll() {
3017                if (isScrollableV) {
3018
3019                    container.append(
3020						$('<div class="jspVerticalBar" />').append(
3021							$('<div class="jspCap jspCapTop" />'),
3022							$('<div class="jspTrack" />').append(
3023								$('<div class="jspDrag" />').append(
3024									$('<div class="jspDragTop" />'),
3025									$('<div class="jspDragBottom" />')
3026								)
3027							),
3028							$('<div class="jspCap jspCapBottom" />')
3029						)
3030					);
3031
3032                    verticalBar = container.find('>.jspVerticalBar');
3033                    verticalTrack = verticalBar.find('>.jspTrack');
3034                    verticalDrag = verticalTrack.find('>.jspDrag');
3035
3036                    if (settings.showArrows) {
3037                        arrowUp = $('<a class="jspArrow jspArrowUp" />').on(
3038							'mousedown.jsp', getArrowScroll(0, -1)
3039						).on('click.jsp', nil);
3040                        arrowDown = $('<a class="jspArrow jspArrowDown" />').on(
3041							'mousedown.jsp', getArrowScroll(0, 1)
3042						).on('click.jsp', nil);
3043                        if (settings.arrowScrollOnHover) {
3044                            arrowUp.on('mouseover.jsp', getArrowScroll(0, -1, arrowUp));
3045                            arrowDown.on('mouseover.jsp', getArrowScroll(0, 1, arrowDown));
3046                        }
3047
3048                        appendArrows(verticalTrack, settings.verticalArrowPositions, arrowUp, arrowDown);
3049                    }
3050
3051                    verticalTrackHeight = paneHeight;
3052                    container.find('>.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow').each(
3053						function () {
3054						    verticalTrackHeight -= $(this).outerHeight();
3055						}
3056					);
3057
3058
3059                    verticalDrag.hover(
3060						function () {
3061						    verticalDrag.addClass('jspHover');
3062						},
3063						function () {
3064						    verticalDrag.removeClass('jspHover');
3065						}
3066					).on(
3067						'mousedown.jsp',
3068						function (e) {
3069						    // Stop IE from allowing text selection
3070						    $('html').on('dragstart.jsp selectstart.jsp', nil);
3071
3072						    verticalDrag.addClass('jspActive');
3073
3074						    var startY = e.pageY - verticalDrag.position().top;
3075
3076						    $('html').on(
3077								'mousemove.jsp',
3078								function (e) {
3079								    positionDragY(e.pageY - startY, false);
3080								}
3081							).on('mouseup.jsp mouseleave.jsp', cancelDrag);
3082						    return false;
3083						}
3084					);
3085                    sizeVerticalScrollbar();
3086                }
3087            }
3088
3089            function sizeVerticalScrollbar() {
3090                verticalTrack.height(verticalTrackHeight + 'px');
3091                verticalDragPosition = 0;
3092                scrollbarWidth = settings.verticalGutter + verticalTrack.outerWidth();
3093
3094                // Make the pane thinner to allow for the vertical scrollbar
3095                pane.width(paneWidth - scrollbarWidth - originalPaddingTotalWidth);
3096
3097                // Add margin to the left of the pane if scrollbars are on that side (to position
3098                // the scrollbar on the left or right set it's left or right property in CSS)
3099                try {
3100                    if (verticalBar.position().left === 0) {
3101                        pane.css('margin-left', scrollbarWidth + 'px');
3102                    }
3103                } catch (err) {
3104                }
3105            }
3106
3107            function initialiseHorizontalScroll() {
3108                if (isScrollableH) {
3109
3110                    container.append(
3111						$('<div class="jspHorizontalBar" />').append(
3112							$('<div class="jspCap jspCapLeft" />'),
3113							$('<div class="jspTrack" />').append(
3114								$('<div class="jspDrag" />').append(
3115									$('<div class="jspDragLeft" />'),
3116									$('<div class="jspDragRight" />')
3117								)
3118							),
3119							$('<div class="jspCap jspCapRight" />')
3120						)
3121					);
3122
3123                    horizontalBar = container.find('>.jspHorizontalBar');
3124                    horizontalTrack = horizontalBar.find('>.jspTrack');
3125                    horizontalDrag = horizontalTrack.find('>.jspDrag');
3126
3127                    if (settings.showArrows) {
3128                        arrowLeft = $('<a class="jspArrow jspArrowLeft" />').on(
3129							'mousedown.jsp', getArrowScroll(-1, 0)
3130						).on('click.jsp', nil);
3131                        arrowRight = $('<a class="jspArrow jspArrowRight" />').on(
3132							'mousedown.jsp', getArrowScroll(1, 0)
3133						).on('click.jsp', nil);
3134                        if (settings.arrowScrollOnHover) {
3135                            arrowLeft.on('mouseover.jsp', getArrowScroll(-1, 0, arrowLeft));
3136                            arrowRight.on('mouseover.jsp', getArrowScroll(1, 0, arrowRight));
3137                        }
3138                        appendArrows(horizontalTrack, settings.horizontalArrowPositions, arrowLeft, arrowRight);
3139                    }
3140
3141                    horizontalDrag.hover(
3142						function () {
3143						    horizontalDrag.addClass('jspHover');
3144						},
3145						function () {
3146						    horizontalDrag.removeClass('jspHover');
3147						}
3148					).on(
3149						'mousedown.jsp',
3150						function (e) {
3151						    // Stop IE from allowing text selection
3152						    $('html').on('dragstart.jsp selectstart.jsp', nil);
3153
3154						    horizontalDrag.addClass('jspActive');
3155
3156						    var startX = e.pageX - horizontalDrag.position().left;
3157
3158						    $('html').on(
3159								'mousemove.jsp',
3160								function (e) {
3161								    positionDragX(e.pageX - startX, false);
3162								}
3163							).on('mouseup.jsp mouseleave.jsp', cancelDrag);
3164						    return false;
3165						}
3166					);
3167                    horizontalTrackWidth = container.innerWidth();
3168                    sizeHorizontalScrollbar();
3169                }
3170            }
3171
3172            function sizeHorizontalScrollbar() {
3173                container.find('>.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow').each(
3174					function () {
3175					    horizontalTrackWidth -= $(this).outerWidth();
3176					}
3177				);
3178
3179                horizontalTrack.width(horizontalTrackWidth + 'px');
3180                horizontalDragPosition = 0;
3181            }
3182
3183            function resizeScrollbars() {
3184                if (isScrollableH && isScrollableV) {
3185                    var horizontalTrackHeight = horizontalTrack.outerHeight(),
3186						verticalTrackWidth = verticalTrack.outerWidth();
3187                    verticalTrackHeight -= horizontalTrackHeight;
3188                    $(horizontalBar).find('>.jspCap:visible,>.jspArrow').each(
3189						function () {
3190						    horizontalTrackWidth += $(this).outerWidth();
3191						}
3192					);
3193                    horizontalTrackWidth -= verticalTrackWidth;
3194                    paneHeight -= verticalTrackWidth;
3195                    paneWidth -= horizontalTrackHeight;
3196                    horizontalTrack.parent().append(
3197						$('<div class="jspCorner" />').css('width', horizontalTrackHeight + 'px')
3198					);
3199                    sizeVerticalScrollbar();
3200                    sizeHorizontalScrollbar();
3201                }
3202                // reflow content
3203                if (isScrollableH) {
3204                    pane.width((container.outerWidth() - originalPaddingTotalWidth) + 'px');
3205                }
3206                contentHeight = pane.outerHeight();
3207                percentInViewV = contentHeight / paneHeight;
3208
3209                if (isScrollableH) {
3210                    horizontalDragWidth = Math.ceil(1 / percentInViewH * horizontalTrackWidth);
3211                    if (horizontalDragWidth > settings.horizontalDragMaxWidth) {
3212                        horizontalDragWidth = settings.horizontalDragMaxWidth;
3213                    } else if (horizontalDragWidth < settings.horizontalDragMinWidth) {
3214                        horizontalDragWidth = settings.horizontalDragMinWidth;
3215                    }
3216                    horizontalDrag.width(horizontalDragWidth + 'px');
3217                    dragMaxX = horizontalTrackWidth - horizontalDragWidth;
3218                    _positionDragX(horizontalDragPosition); // To update the state for the arrow buttons
3219                }
3220                if (isScrollableV) {
3221                    verticalDragHeight = Math.ceil(1 / percentInViewV * verticalTrackHeight);
3222                    if (verticalDragHeight > settings.verticalDragMaxHeight) {
3223                        verticalDragHeight = settings.verticalDragMaxHeight;
3224                    } else if (verticalDragHeight < settings.verticalDragMinHeight) {
3225                        verticalDragHeight = settings.verticalDragMinHeight;
3226                    }
3227                    verticalDrag.height(verticalDragHeight + 'px');
3228                    dragMaxY = verticalTrackHeight - verticalDragHeight;
3229                    _positionDragY(verticalDragPosition); // To update the state for the arrow buttons
3230                }
3231            }
3232
3233            function appendArrows(ele, p, a1, a2) {
3234                var p1 = "before", p2 = "after", aTemp;
3235
3236                // Sniff for mac... Is there a better way to determine whether the arrows would naturally appear
3237                // at the top or the bottom of the bar?
3238                if (p == "os") {
3239                    p = /Mac/.test(navigator.platform) ? "after" : "split";
3240                }
3241                if (p == p1) {
3242                    p2 = p;
3243                } else if (p == p2) {
3244                    p1 = p;
3245                    aTemp = a1;
3246                    a1 = a2;
3247                    a2 = aTemp;
3248                }
3249
3250                ele[p1](a1)[p2](a2);
3251            }
3252
3253            function getArrowScroll(dirX, dirY, ele) {
3254                return function () {
3255                    arrowScroll(dirX, dirY, this, ele);
3256                    this.blur();
3257                    return false;
3258                };
3259            }
3260
3261            function arrowScroll(dirX, dirY, arrow, ele) {
3262                arrow = $(arrow).addClass('jspActive');
3263
3264                var eve,
3265					scrollTimeout,
3266					isFirst = true,
3267					doScroll = function () {
3268					    if (dirX !== 0) {
3269					        jsp.scrollByX(dirX * settings.arrowButtonSpeed);
3270					    }
3271					    if (dirY !== 0) {
3272					        jsp.scrollByY(dirY * settings.arrowButtonSpeed);
3273					    }
3274					    scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.arrowRepeatFreq);
3275					    isFirst = false;
3276					};
3277
3278                doScroll();
3279
3280                eve = ele ? 'mouseout.jsp' : 'mouseup.jsp';
3281                ele = ele || $('html');
3282                ele.on(
3283					eve,
3284					function () {
3285					    arrow.removeClass('jspActive');
3286					    scrollTimeout && clearTimeout(scrollTimeout);
3287					    scrollTimeout = null;
3288					    ele.off(eve);
3289					}
3290				);
3291            }
3292
3293            function initClickOnTrack() {
3294                removeClickOnTrack();
3295                if (isScrollableV) {
3296                    verticalTrack.on(
3297						'mousedown.jsp',
3298						function (e) {
3299						    if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
3300						        var clickedTrack = $(this),
3301									offset = clickedTrack.offset(),
3302									direction = e.pageY - offset.top - verticalDragPosition,
3303									scrollTimeout,
3304									isFirst = true,
3305									doScroll = function () {
3306									    var offset = clickedTrack.offset(),
3307											pos = e.pageY - offset.top - verticalDragHeight / 2,
3308											contentDragY = paneHeight * settings.scrollPagePercent,
3309											dragY = dragMaxY * contentDragY / (contentHeight - paneHeight);
3310									    if (direction < 0) {
3311									        if (verticalDragPosition - dragY > pos) {
3312									            jsp.scrollByY(-contentDragY);
3313									        } else {
3314									            positionDragY(pos);
3315									        }
3316									    } else if (direction > 0) {
3317									        if (verticalDragPosition + dragY < pos) {
3318									            jsp.scrollByY(contentDragY);
3319									        } else {
3320									            positionDragY(pos);
3321									        }
3322									    } else {
3323									        cancelClick();
3324									        return;
3325									    }
3326									    scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
3327									    isFirst = false;
3328									},
3329									cancelClick = function () {
3330									    scrollTimeout && clearTimeout(scrollTimeout);
3331									    scrollTimeout = null;
3332									    $(document).off('mouseup.jsp', cancelClick);
3333									};
3334						        doScroll();
3335						        $(document).on('mouseup.jsp', cancelClick);
3336						        return false;
3337						    }
3338						}
3339					);
3340                }
3341
3342                if (isScrollableH) {
3343                    horizontalTrack.on(
3344						'mousedown.jsp',
3345						function (e) {
3346						    if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
3347						        var clickedTrack = $(this),
3348									offset = clickedTrack.offset(),
3349									direction = e.pageX - offset.left - horizontalDragPosition,
3350									scrollTimeout,
3351									isFirst = true,
3352									doScroll = function () {
3353									    var offset = clickedTrack.offset(),
3354											pos = e.pageX - offset.left - horizontalDragWidth / 2,
3355											contentDragX = paneWidth * settings.scrollPagePercent,
3356											dragX = dragMaxX * contentDragX / (contentWidth - paneWidth);
3357									    if (direction < 0) {
3358									        if (horizontalDragPosition - dragX > pos) {
3359									            jsp.scrollByX(-contentDragX);
3360									        } else {
3361									            positionDragX(pos);
3362									        }
3363									    } else if (direction > 0) {
3364									        if (horizontalDragPosition + dragX < pos) {
3365									            jsp.scrollByX(contentDragX);
3366									        } else {
3367									            positionDragX(pos);
3368									        }
3369									    } else {
3370									        cancelClick();
3371									        return;
3372									    }
3373									    scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
3374									    isFirst = false;
3375									},
3376									cancelClick = function () {
3377									    scrollTimeout && clearTimeout(scrollTimeout);
3378									    scrollTimeout = null;
3379									    $(document).off('mouseup.jsp', cancelClick);
3380									};
3381						        doScroll();
3382						        $(document).on('mouseup.jsp', cancelClick);
3383						        return false;
3384						    }
3385						}
3386					);
3387                }
3388            }
3389
3390            function removeClickOnTrack() {
3391                if (horizontalTrack) {
3392                    horizontalTrack.off('mousedown.jsp');
3393                }
3394                if (verticalTrack) {
3395                    verticalTrack.off('mousedown.jsp');
3396                }
3397            }
3398
3399            function cancelDrag() {
3400                $('html').off('dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp');
3401
3402                if (verticalDrag) {
3403                    verticalDrag.removeClass('jspActive');
3404                }
3405                if (horizontalDrag) {
3406                    horizontalDrag.removeClass('jspActive');
3407                }
3408            }
3409
3410            function positionDragY(destY, animate) {
3411                if (!isScrollableV) {
3412                    return;
3413                }
3414                if (destY < 0) {
3415                    destY = 0;
3416                } else if (destY > dragMaxY) {
3417                    destY = dragMaxY;
3418                }
3419
3420                // can't just check if(animate) because false is a valid value that could be passed in...
3421                if (animate === undefined) {
3422                    animate = settings.animateScroll;
3423                }
3424                if (animate) {
3425                    jsp.animate(verticalDrag, 'top', destY, _positionDragY);
3426                } else {
3427                    verticalDrag.css('top', destY);
3428                    _positionDragY(destY);
3429                }
3430
3431            }
3432
3433            function _positionDragY(destY) {
3434                if (destY === undefined) {
3435                    destY = verticalDrag.position().top;
3436                }
3437
3438                container.scrollTop(0);
3439                verticalDragPosition = destY;
3440
3441                var isAtTop = verticalDragPosition === 0,
3442					isAtBottom = verticalDragPosition == dragMaxY,
3443					percentScrolled = destY / dragMaxY,
3444					destTop = -percentScrolled * (contentHeight - paneHeight);
3445
3446                if (wasAtTop != isAtTop || wasAtBottom != isAtBottom) {
3447                    wasAtTop = isAtTop;
3448                    wasAtBottom = isAtBottom;
3449                    elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
3450                }
3451
3452                updateVerticalArrows(isAtTop, isAtBottom);
3453                pane.css('top', destTop);
3454                elem.trigger('jsp-scroll-y', [-destTop, isAtTop, isAtBottom]).trigger('scroll');
3455            }
3456
3457            function positionDragX(destX, animate) {
3458                if (!isScrollableH) {
3459                    return;
3460                }
3461                if (destX < 0) {
3462                    destX = 0;
3463                } else if (destX > dragMaxX) {
3464                    destX = dragMaxX;
3465                }
3466
3467                if (animate === undefined) {
3468                    animate = settings.animateScroll;
3469                }
3470                if (animate) {
3471                    jsp.animate(horizontalDrag, 'left', destX, _positionDragX);
3472                } else {
3473                    horizontalDrag.css('left', destX);
3474                    _positionDragX(destX);
3475                }
3476            }
3477
3478            function _positionDragX(destX) {
3479                if (destX === undefined) {
3480                    destX = horizontalDrag.position().left;
3481                }
3482
3483                container.scrollTop(0);
3484                horizontalDragPosition = destX;
3485
3486                var isAtLeft = horizontalDragPosition === 0,
3487					isAtRight = horizontalDragPosition == dragMaxX,
3488					percentScrolled = destX / dragMaxX,
3489					destLeft = -percentScrolled * (contentWidth - paneWidth);
3490
3491                if (wasAtLeft != isAtLeft || wasAtRight != isAtRight) {
3492                    wasAtLeft = isAtLeft;
3493                    wasAtRight = isAtRight;
3494                    elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
3495                }
3496
3497                updateHorizontalArrows(isAtLeft, isAtRight);
3498                pane.css('left', destLeft);
3499                elem.trigger('jsp-scroll-x', [-destLeft, isAtLeft, isAtRight]).trigger('scroll');
3500            }
3501
3502            function updateVerticalArrows(isAtTop, isAtBottom) {
3503                if (settings.showArrows) {
3504                    arrowUp[isAtTop ? 'addClass' : 'removeClass']('jspDisabled');
3505                    arrowDown[isAtBottom ? 'addClass' : 'removeClass']('jspDisabled');
3506                }
3507            }
3508
3509            function updateHorizontalArrows(isAtLeft, isAtRight) {
3510                if (settings.showArrows) {
3511                    arrowLeft[isAtLeft ? 'addClass' : 'removeClass']('jspDisabled');
3512                    arrowRight[isAtRight ? 'addClass' : 'removeClass']('jspDisabled');
3513                }
3514            }
3515
3516            function scrollToY(destY, animate) {
3517                var percentScrolled = destY / (contentHeight - paneHeight);
3518                positionDragY(percentScrolled * dragMaxY, animate);
3519            }
3520
3521            function scrollToX(destX, animate) {
3522                var percentScrolled = destX / (contentWidth - paneWidth);
3523                positionDragX(percentScrolled * dragMaxX, animate);
3524            }
3525
3526            function scrollToElement(ele, stickToTop, animate) {
3527                var e, eleHeight, eleWidth, eleTop = 0, eleLeft = 0, viewportTop, viewportLeft, maxVisibleEleTop, maxVisibleEleLeft, destY, destX;
3528
3529                // Legal hash values aren't necessarily legal jQuery selectors so we need to catch any
3530                // errors from the lookup...
3531                try {
3532                    e = $(ele);
3533                } catch (err) {
3534                    return;
3535                }
3536                eleHeight = e.outerHeight();
3537                eleWidth = e.outerWidth();
3538
3539                container.scrollTop(0);
3540                container.scrollLeft(0);
3541
3542                // loop through parents adding the offset top of any elements that are relatively positioned between
3543                // the focused element and the jspPane so we can get the true distance from the top
3544                // of the focused element to the top of the scrollpane...
3545                while (!e.is('.jspPane')) {
3546                    eleTop += e.position().top;
3547                    eleLeft += e.position().left;
3548                    e = e.offsetParent();
3549                    if (/^body|html$/i.test(e[0].nodeName)) {
3550                        // we ended up too high in the document structure. Quit!
3551                        return;
3552                    }
3553                }
3554
3555                viewportTop = contentPositionY();
3556                maxVisibleEleTop = viewportTop + paneHeight;
3557                if (eleTop < viewportTop || stickToTop) { // element is above viewport
3558                    destY = eleTop - settings.verticalGutter;
3559                } else if (eleTop + eleHeight > maxVisibleEleTop) { // element is below viewport
3560                    destY = eleTop - paneHeight + eleHeight + settings.verticalGutter;
3561                }
3562                if (destY) {
3563                    scrollToY(destY, animate);
3564                }
3565
3566                viewportLeft = contentPositionX();
3567                maxVisibleEleLeft = viewportLeft + paneWidth;
3568                if (eleLeft < viewportLeft || stickToTop) { // element is to the left of viewport
3569                    destX = eleLeft - settings.horizontalGutter;
3570                } else if (eleLeft + eleWidth > maxVisibleEleLeft) { // element is to the right viewport
3571                    destX = eleLeft - paneWidth + eleWidth + settings.horizontalGutter;
3572                }
3573                if (destX) {
3574                    scrollToX(destX, animate);
3575                }
3576
3577            }
3578
3579            function contentPositionX() {
3580                return -pane.position().left;
3581            }
3582
3583            function contentPositionY() {
3584                return -pane.position().top;
3585            }
3586
3587            function isCloseToBottom() {
3588                var scrollableHeight = contentHeight - paneHeight;
3589                return (scrollableHeight > 20) && (scrollableHeight - contentPositionY() < 10);
3590            }
3591
3592            function isCloseToRight() {
3593                var scrollableWidth = contentWidth - paneWidth;
3594                return (scrollableWidth > 20) && (scrollableWidth - contentPositionX() < 10);
3595            }
3596
3597            function initMousewheel() {
3598                container.off(mwEvent).on(
3599					mwEvent,
3600					function (event, delta, deltaX, deltaY) {
3601					    var dX = horizontalDragPosition, dY = verticalDragPosition;
3602					    jsp.scrollBy(deltaX * settings.mouseWheelSpeed, -deltaY * settings.mouseWheelSpeed, false);
3603					    // return true if there was no movement so rest of screen can scroll
3604					    return dX == horizontalDragPosition && dY == verticalDragPosition;
3605					}
3606				);
3607            }
3608
3609            function removeMousewheel() {
3610                container.off(mwEvent);
3611            }
3612
3613            function nil() {
3614                return false;
3615            }
3616
3617            function initFocusHandler() {
3618                pane.find(':input,a').off('focus.jsp').on(
3619					'focus.jsp',
3620					function (e) {
3621					    scrollToElement(e.target, false);
3622					}
3623				);
3624            }
3625
3626            function removeFocusHandler() {
3627                pane.find(':input,a').off('focus.jsp');
3628            }
3629
3630            function initKeyboardNav() {
3631                var keyDown, elementHasScrolled, validParents = [];
3632                isScrollableH && validParents.push(horizontalBar[0]);
3633                isScrollableV && validParents.push(verticalBar[0]);
3634
3635                // IE also focuses elements that don't have tabindex set.
3636                pane.focus(
3637					function () {
3638					    elem.focus();
3639					}
3640				);
3641
3642                elem.attr('tabindex', 0)
3643					.off('keydown.jsp keypress.jsp')
3644					.on(
3645						'keydown.jsp',
3646						function (e) {
3647						    if (e.target !== this && !(validParents.length && $(e.target).closest(validParents).length)) {
3648						        return;
3649						    }
3650						    var dX = horizontalDragPosition, dY = verticalDragPosition;
3651						    switch (e.keyCode) {
3652						        case 40: // down
3653						        case 38: // up
3654						        case 34: // page down
3655						        case 32: // space
3656						        case 33: // page up
3657						        case 39: // right
3658						        case 37: // left
3659						            keyDown = e.keyCode;
3660						            keyDownHandler();
3661						            break;
3662						        case 35: // end
3663						            scrollToY(contentHeight - paneHeight);
3664						            keyDown = null;
3665						            break;
3666						        case 36: // home
3667						            scrollToY(0);
3668						            keyDown = null;
3669						            break;
3670						    }
3671
3672						    elementHasScrolled = e.keyCode == keyDown && dX != horizontalDragPosition || dY != verticalDragPosition;
3673						    return !elementHasScrolled;
3674						}
3675					).off(
3676						'keypress.jsp', // For FF/ OSX so that we can cancel the repeat key presses if the JSP scrolls...
3677						function (e) {
3678						    if (e.keyCode == keyDown) {
3679						        keyDownHandler();
3680						    }
3681						    return !elementHasScrolled;
3682						}
3683					);
3684
3685                if (settings.hideFocus) {
3686                    elem.css('outline', 'none');
3687                    if ('hideFocus' in container[0]) {
3688                        elem.attr('hideFocus', true);
3689                    }
3690                } else {
3691                    elem.css('outline', '');
3692                    if ('hideFocus' in container[0]) {
3693                        elem.attr('hideFocus', false);
3694                    }
3695                }
3696
3697                function keyDownHandler() {
3698                    var dX = horizontalDragPosition, dY = verticalDragPosition;
3699                    switch (keyDown) {
3700                        case 40: // down
3701                            jsp.scrollByY(settings.keyboardSpeed, false);
3702                            break;
3703                        case 38: // up
3704                            jsp.scrollByY(-settings.keyboardSpeed, false);
3705                            break;
3706                        case 34: // page down
3707                        case 32: // space
3708                            jsp.scrollByY(paneHeight * settings.scrollPagePercent, false);
3709                            break;
3710                        case 33: // page up
3711                            jsp.scrollByY(-paneHeight * settings.scrollPagePercent, false);
3712                            break;
3713                        case 39: // right
3714                            jsp.scrollByX(settings.keyboardSpeed, false);
3715                            break;
3716                        case 37: // left
3717                            jsp.scrollByX(-settings.keyboardSpeed, false);
3718                            break;
3719                    }
3720
3721                    elementHasScrolled = dX != horizontalDragPosition || dY != verticalDragPosition;
3722                    return elementHasScrolled;
3723                }
3724            }
3725
3726            function removeKeyboardNav() {
3727                elem.attr('tabindex', '-1')
3728					.removeAttr('tabindex')
3729					.off('keydown.jsp keypress.jsp');
3730            }
3731
3732            function observeHash() {
3733                if (location.hash && location.hash.length > 1) {
3734                    var e,
3735						retryInt,
3736						hash = escape(location.hash.substr(1)) // hash must be escaped to prevent XSS
3737                    ;
3738                    try {
3739                        e = $('#' + hash + ', a[name="' + hash + '"]');
3740                    } catch (err) {
3741                        return;
3742                    }
3743
3744                    if (e.length && pane.find(hash)) {
3745                        // nasty workaround but it appears to take a little while before the hash has done its thing
3746                        // to the rendered page so we just wait until the container's scrollTop has been messed up.
3747                        if (container.scrollTop() === 0) {
3748                            retryInt = setInterval(
3749								function () {
3750								    if (container.scrollTop() > 0) {
3751								        scrollToElement(e, true);
3752								        $(document).scrollTop(container.position().top);
3753								        clearInterval(retryInt);
3754								    }
3755								},
3756								50
3757							);
3758                        } else {
3759                            scrollToElement(e, true);
3760                            $(document).scrollTop(container.position().top);
3761                        }
3762                    }
3763                }
3764            }
3765
3766            function hijackInternalLinks() {
3767                // only register the link handler once
3768                if ($(document.body).data('jspHijack')) {
3769                    return;
3770                }
3771
3772                // remember that the handler was bound
3773                $(document.body).data('jspHijack', true);
3774
3775                // use live handler to also capture newly created links
3776                $(document.body).delegate('a[href*=#]', 'click', function (event) {
3777                    // does the link point to the same page?
3778                    // this also takes care of cases with a <base>-Tag or Links not starting with the hash #
3779                    // e.g. <a href="index.html#test"> when the current url already is index.html
3780                    var href = this.href.substr(0, this.href.indexOf('#')),
3781						locationHref = location.href,
3782						hash,
3783						element,
3784						container,
3785						jsp,
3786						scrollTop,
3787						elementTop;
3788                    if (location.href.indexOf('#') !== -1) {
3789                        locationHref = location.href.substr(0, location.href.indexOf('#'));
3790                    }
3791                    if (href !== locationHref) {
3792                        // the link points to another page
3793                        return;
3794                    }
3795
3796                    // check if jScrollPane should handle this click event
3797                    hash = escape(this.href.substr(this.href.indexOf('#') + 1));
3798
3799                    // find the element on the page
3800                    element;
3801                    try {
3802                        element = $('#' + hash + ', a[name="' + hash + '"]');
3803                    } catch (e) {
3804                        // hash is not a valid jQuery identifier
3805                        return;
3806                    }
3807
3808                    if (!element.length) {
3809                        // this link does not point to an element on this page
3810                        return;
3811                    }
3812
3813                    container = element.closest('.jspScrollable');
3814                    jsp = container.data('jsp');
3815
3816                    // jsp might be another jsp instance than the one, that bound this event
3817                    // remember: this event is only bound once for all instances.
3818                    jsp.scrollToElement(element, true);
3819
3820                    if (container[0].scrollIntoView) {
3821                        // also scroll to the top of the container (if it is not visible)
3822                        scrollTop = $(window).scrollTop();
3823                        elementTop = element.offset().top;
3824                        if (elementTop < scrollTop || elementTop > scrollTop + $(window).height()) {
3825                            container[0].scrollIntoView();
3826                        }
3827                    }
3828
3829                    // jsp handled this event, prevent the browser default (scrolling :P)
3830                    event.preventDefault();
3831                });
3832            }
3833
3834            // Init touch on iPad, iPhone, iPod, Android
3835            function initTouch() {
3836                var startX,
3837					startY,
3838					touchStartX,
3839					touchStartY,
3840					moved,
3841					moving = false;
3842
3843                container.off('touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick').on(
3844					'touchstart.jsp',
3845					function (e) {
3846					    var touch = e.originalEvent.touches[0];
3847					    startX = contentPositionX();
3848					    startY = contentPositionY();
3849					    touchStartX = touch.pageX;
3850					    touchStartY = touch.pageY;
3851					    moved = false;
3852					    moving = true;
3853					}
3854				).on(
3855					'touchmove.jsp',
3856					function (ev) {
3857					    if (!moving) {
3858					        return;
3859					    }
3860
3861					    var touchPos = ev.originalEvent.touches[0],
3862							dX = horizontalDragPosition, dY = verticalDragPosition;
3863
3864					    jsp.scrollTo(startX + touchStartX - touchPos.pageX, startY + touchStartY - touchPos.pageY);
3865
3866					    moved = moved || Math.abs(touchStartX - touchPos.pageX) > 5 || Math.abs(touchStartY - touchPos.pageY) > 5;
3867
3868					    // return true if there was no movement so rest of screen can scroll
3869					    return dX == horizontalDragPosition && dY == verticalDragPosition;
3870					}
3871				).on(
3872					'touchend.jsp',
3873					function (e) {
3874					    moving = false;
3875					    /*if(moved) {
3876							return false;
3877						}*/
3878					}
3879				).on(
3880					'click.jsp-touchclick',
3881					function (e) {
3882					    if (moved) {
3883					        moved = false;
3884					        return false;
3885					    }
3886					}
3887				);
3888            }
3889
3890            function destroy() {
3891                var currentY = contentPositionY(),
3892					currentX = contentPositionX();
3893                elem.removeClass('jspScrollable').off('.jsp');
3894                elem.replaceWith(originalElement.append(pane.children()));
3895                originalElement.scrollTop(currentY);
3896                originalElement.scrollLeft(currentX);
3897
3898                // clear reinitialize timer if active
3899                if (reinitialiseInterval) {
3900                    clearInterval(reinitialiseInterval);
3901                }
3902            }
3903
3904            // Public API
3905            $.extend(
3906				jsp,
3907				{
3908				    // Reinitialises the scroll pane (if it's internal dimensions have changed since the last time it
3909				    // was initialised). The settings object which is passed in will override any settings from the
3910				    // previous time it was initialised - if you don't pass any settings then the ones from the previous
3911				    // initialisation will be used.
3912				    reinitialise: function (s) {
3913				        s = $.extend({}, settings, s);
3914				        initialise(s);
3915				    },
3916				    // Scrolls the specified element (a jQuery object, DOM node or jQuery selector string) into view so
3917				    // that it can be seen within the viewport. If stickToTop is true then the element will appear at
3918				    // the top of the viewport, if it is false then the viewport will scroll as little as possible to
3919				    // show the element. You can also specify if you want animation to occur. If you don't provide this
3920				    // argument then the animateScroll value from the settings object is used instead.
3921				    scrollToElement: function (ele, stickToTop, animate) {
3922				        scrollToElement(ele, stickToTop, animate);
3923				    },
3924				    // Scrolls the pane so that the specified co-ordinates within the content are at the top left
3925				    // of the viewport. animate is optional and if not passed then the value of animateScroll from
3926				    // the settings object this jScrollPane was initialised with is used.
3927				    scrollTo: function (destX, destY, animate) {
3928				        scrollToX(destX, animate);
3929				        scrollToY(destY, animate);
3930				    },
3931				    // Scrolls the pane so that the specified co-ordinate within the content is at the left of the
3932				    // viewport. animate is optional and if not passed then the value of animateScroll from the settings
3933				    // object this jScrollPane was initialised with is used.
3934				    scrollToX: function (destX, animate) {
3935				        scrollToX(destX, animate);
3936				    },
3937				    // Scrolls the pane so that the specified co-ordinate within the content is at the top of the
3938				    // viewport. animate is optional and if not passed then the value of animateScroll from the settings
3939				    // object this jScrollPane was initialised with is used.
3940				    scrollToY: function (destY, animate) {
3941				        scrollToY(destY, animate);
3942				    },
3943				    // Scrolls the pane to the specified percentage of its maximum horizontal scroll position. animate
3944				    // is optional and if not passed then the value of animateScroll from the settings object this
3945				    // jScrollPane was initialised with is used.
3946				    scrollToPercentX: function (destPercentX, animate) {
3947				        scrollToX(destPercentX * (contentWidth - paneWidth), animate);
3948				    },
3949				    // Scrolls the pane to the specified percentage of its maximum vertical scroll position. animate
3950				    // is optional and if not passed then the value of animateScroll from the settings object this
3951				    // jScrollPane was initialised with is used.
3952				    scrollToPercentY: function (destPercentY, animate) {
3953				        scrollToY(destPercentY * (contentHeight - paneHeight), animate);
3954				    },
3955				    // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
3956				    // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
3957				    scrollBy: function (deltaX, deltaY, animate) {
3958				        jsp.scrollByX(deltaX, animate);
3959				        jsp.scrollByY(deltaY, animate);
3960				    },
3961				    // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
3962				    // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
3963				    scrollByX: function (deltaX, animate) {
3964				        var destX = contentPositionX() + Math[deltaX < 0 ? 'floor' : 'ceil'](deltaX),
3965							percentScrolled = destX / (contentWidth - paneWidth);
3966				        positionDragX(percentScrolled * dragMaxX, animate);
3967				    },
3968				    // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
3969				    // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
3970				    scrollByY: function (deltaY, animate) {
3971				        var destY = contentPositionY() + Math[deltaY < 0 ? 'floor' : 'ceil'](deltaY),
3972							percentScrolled = destY / (contentHeight - paneHeight);
3973				        positionDragY(percentScrolled * dragMaxY, animate);
3974				    },
3975				    // Positions the horizontal drag at the specified x position (and updates the viewport to reflect
3976				    // this). animate is optional and if not passed then the value of animateScroll from the settings
3977				    // object this jScrollPane was initialised with is used.
3978				    positionDragX: function (x, animate) {
3979				        positionDragX(x, animate);
3980				    },
3981				    // Positions the vertical drag at the specified y position (and updates the viewport to reflect
3982				    // this). animate is optional and if not passed then the value of animateScroll from the settings
3983				    // object this jScrollPane was initialised with is used.
3984				    positionDragY: function (y, animate) {
3985				        positionDragY(y, animate);
3986				    },
3987				    // This method is called when jScrollPane is trying to animate to a new position. You can override
3988				    // it if you want to provide advanced animation functionality. It is passed the following arguments:
3989				    //  * ele          - the element whose position is being animated
3990				    //  * prop         - the property that is being animated
3991				    //  * value        - the value it's being animated to
3992				    //  * stepCallback - a function that you must execute each time you update the value of the property
3993				    // You can use the default implementation (below) as a starting point for your own implementation.
3994				    animate: function (ele, prop, value, stepCallback) {
3995				        var params = {};
3996				        params[prop] = value;
3997				        ele.animate(
3998							params,
3999							{
4000							    'duration': settings.animateDuration,
4001							    'easing': settings.animateEase,
4002							    'queue': false,
4003							    'step': stepCallback
4004							}
4005						);
4006				    },
4007				    // Returns the current x position of the viewport with regards to the content pane.
4008				    getContentPositionX: function () {
4009				        return contentPositionX();
4010				    },
4011				    // Returns the current y position of the viewport with regards to the content pane.
4012				    getContentPositionY: function () {
4013				        return contentPositionY();
4014				    },
4015				    // Returns the width of the content within the scroll pane.
4016				    getContentWidth: function () {
4017				        return contentWidth;
4018				    },
4019				    // Returns the height of the content within the scroll pane.
4020				    getContentHeight: function () {
4021				        return contentHeight;
4022				    },
4023				    // Returns the horizontal position of the viewport within the pane content.
4024				    getPercentScrolledX: function () {
4025				        return contentPositionX() / (contentWidth - paneWidth);
4026				    },
4027				    // Returns the vertical position of the viewport within the pane content.
4028				    getPercentScrolledY: function () {
4029				        return contentPositionY() / (contentHeight - paneHeight);
4030				    },
4031				    // Returns whether or not this scrollpane has a horizontal scrollbar.
4032				    getIsScrollableH: function () {
4033				        return isScrollableH;
4034				    },
4035				    // Returns whether or not this scrollpane has a vertical scrollbar.
4036				    getIsScrollableV: function () {
4037				        return isScrollableV;
4038				    },
4039				    // Gets a reference to the content pane. It is important that you use this method if you want to
4040				    // edit the content of your jScrollPane as if you access the element directly then you may have some
4041				    // problems (as your original element has had additional elements for the scrollbars etc added into
4042				    // it).
4043				    getContentPane: function () {
4044				        return pane;
4045				    },
4046				    // Scrolls this jScrollPane down as far as it can currently scroll. If animate isn't passed then the
4047				    // animateScroll value from settings is used instead.
4048				    scrollToBottom: function (animate) {
4049				        positionDragY(dragMaxY, animate);
4050				    },
4051				    // Hijacks the links on the page which link to content inside the scrollpane. If you have changed
4052				    // the content of your page (e.g. via AJAX) and want to make sure any new anchor links to the
4053				    // contents of your scroll pane will work then call this function.
4054				    hijackInternalLinks: $.noop,
4055				    // Removes the jScrollPane and returns the page to the state it was in before jScrollPane was
4056				    // initialised.
4057				    destroy: function () {
4058				        destroy();
4059				    }
4060				}
4061			);
4062
4063            initialise(s);
4064        }
4065
4066        // Pluginifying code...
4067        settings = $.extend({}, $.fn.jScrollPane.defaults, settings);
4068
4069        // Apply default speed
4070        $.each(['mouseWheelSpeed', 'arrowButtonSpeed', 'trackClickSpeed', 'keyboardSpeed'], function () {
4071            settings[this] = settings[this] || settings.speed;
4072        });
4073
4074        return this.each(
4075			function () {
4076			    var elem = $(this), jspApi = elem.data('jsp');
4077			    if (jspApi) {
4078			        jspApi.reinitialise(settings);
4079			    } else {
4080			        $("script", elem).filter('[type="text/javascript"], :not([type])').remove();
4081			        jspApi = new JScrollPane(elem, settings);
4082			        elem.data('jsp', jspApi);
4083			    }
4084			}
4085		);
4086    };
4087
4088    $.fn.jScrollPane.defaults = {
4089        showArrows: false,
4090        maintainPosition: true,
4091        stickToBottom: false,
4092        stickToRight: false,
4093        clickOnTrack: true,
4094        autoReinitialise: false,
4095        autoReinitialiseDelay: 500,
4096        verticalDragMinHeight: 30,
4097        verticalDragMaxHeight: 99999,
4098        horizontalDragMinWidth: 30,
4099        horizontalDragMaxWidth: 99999,
4100        contentWidth: undefined,
4101        animateScroll: false,
4102        animateDuration: 300,
4103        animateEase: 'linear',
4104        hijackInternalLinks: false,
4105        verticalGutter: 4,
4106        horizontalGutter: 4,
4107        mouseWheelSpeed: 0,
4108        arrowButtonSpeed: 0,
4109        arrowRepeatFreq: 50,
4110        arrowScrollOnHover: false,
4111        trackClickSpeed: 0,
4112        trackClickRepeatFreq: 70,
4113        verticalArrowPositions: 'split',
4114        horizontalArrowPositions: 'split',
4115        enableKeyboardNavigation: true,
4116        hideFocus: false,
4117        keyboardSpeed: 0,
4118        initialDelay: 300,        // Delay before starting repeating
4119        speed: 30,		// Default speed when others falsey
4120        scrollPagePercent: .8		// Percent of visible area scrolled when pageUp/Down or track area pressed
4121    };
4122
4123})(jQuery);
4124
4125(function ($) {
4126    $.fn.dnnSettingDropdown = function () {
4127        var clicked = function () {
4128            if ($(this).hasClass('dnnButtonDropdown')) {
4129                $(this).removeClass('dnnButtonDropdown').addClass('dnnButtonDropdown-clicked');
4130                $(this).next().show();
4131            }
4132        };
4133
4134        var hideDropdown = function () {
4135            var btn = $(this).children(':first');
4136            if (btn.hasClass('dnnButtonDropdown-clicked')) {
4137                btn.removeClass('dnnButtonDropdown-clicked').addClass('dnnButtonDropdown');
4138                btn.next().fadeOut();
4139            }
4140        };
4141
4142        var hoverConfig = {
4143            over: function () {
4144            },
4145            out: hideDropdown,
4146            timout: 600
4147        };
4148
4149        return $(this).each(function () {
4150            $(this).off('click', clicked).on('click', clicked);
4151            $(this).parent().hoverIntent(hoverConfig);
4152        });
4153    };
4154})(jQuery);
4155
4156(function ($) {
4157    $.fn.onEnter = function (fn) {
4158        return this.each(function () {
4159            var $this = $(this);
4160            $this.on('onEnter', fn);
4161            $this.keydown(function (e) {
4162                if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
4163                    e.preventDefault();
4164                    e.stopPropagation();
4165                    $this.trigger('onEnter');
4166                }
4167            });
4168        });
4169    };
4170})(jQuery);
4171
4172(function ($) {
4173    $.extend({
4174        onAjaxError: function (jqXhr, textStatus, errorThrown) {
4175            var title, text;
4176            if (jqXhr && jqXhr.status === 401) {
4177                dnnModal.show('../Login.aspx' + '?popUp=true', true, 300, 650, true, '');
4178                return;
4179            }
4180            if (jqXhr && jqXhr.responseText && jqXhr.statusText) {
4181                try {
4182                    title = jqXhr.statusText + " (" + jqXhr.status + ")";
4183                    text = JSON.parse(jqXhr.responseText).Message;
4184                }
4185                catch (e) {
4186                    text = errorThrown;
4187                }
4188            }
4189            $.dnnAlert({ title: title || "Error", text: text || "Unknown error" });
4190        }
4191    });
4192})(jQuery);
4193
4194(function ($) {
4195	$.fn.dnnSliderInput = function (options) {
4196		var sliderOptions = $.extend({}, $.fn.dnnSliderInput.defaults, options);
4197    	return $(this).each(function () {
4198    		var $this = $(this);
4199		    var value = $this.val();
4200		    var $slider = $('<div class="dnnSliderInput"></div>');
4201		    $this.hide().after($slider);
4202
4203		    $slider.slider(sliderOptions);
4204		    $slider.slider('value', value);
4205
4206		    var $tooltip = $('<span class="dnnTooltip"><span class="dnnFormHelpContent dnnClear"><span class="dnnHelpText bottomArrow"></span></span></span>');
4207
4208		    var calcTooltipPosition = function () {
4209			    setTimeout(function() {
4210				    var left = $slider.find('.ui-slider-handle')[0].style.left;
4211				    $tooltip.css('left', left);
4212			    }, 0);
4213		    };
4214
4215		    $tooltip.find('.dnnHelpText').html(value);
4216		    $tooltip.data('initialized', true);
4217			$slider.append($tooltip);
4218
4219		    calcTooltipPosition();
4220		    $slider.on('slide', function(event, ui) {
4221		    	$tooltip.find('.dnnHelpText').html(ui.value);
4222		    	$this.val(ui.value);
4223			    calcTooltipPosition();
4224		    });
4225	    });
4226    };
4227
4228	$.fn.dnnSliderInput.defaults = {
4229		min: 0,
4230		max: 100,
4231		step: 1
4232	}
4233})(jQuery);
4234
4235// please keep this func at last of this file, thanks
4236(function ($) {
4237    /* Start customised controls */
4238    var inputFocusFix = function () {
4239        var errorMsg = $(this).next();
4240        if (errorMsg.hasClass('dnnFormError'))
4241            errorMsg.hide();
4242    };
4243    var throttle = null;
4244    var dnnInitCustomisedCtrls = function () {
4245        if (throttle != null) {
4246            clearTimeout(throttle);
4247            throttle = null;
4248        }
4249        throttle = setTimeout(function () {
4250            $('.dnnForm input[type="checkbox"]').dnnCheckbox();
4251            $('.dnnForm input[type="radio"]').dnnCheckbox({ cls: 'dnnRadiobutton' });
4252            $('.dnnTooltip').dnnTooltip();
4253            $('.dnnForm input[type="text"], .dnnForm input[type="password"]').off('focus', inputFocusFix).on('focus', inputFocusFix);
4254            $('.dnnForm :file').dnnFileInput();
4255	        $('.dnnForm input[data-default]').dnnPlaceholder();
4256        }, 200);
4257        //change the window confirm style to DNN style
4258        $("*[onclick*='return confirm']").each(function () {
4259            var instance = $(this);
4260            var isButton = this.nodeName.toLowerCase() == "img" || this.nodeName.toLowerCase() == "input";
4261            var script = /return confirm\((['"])([\s\S]*?)\1\)/g.exec(instance.attr("onclick"));
4262            if (script != null) {
4263                var confirmContent = script[2].split("\\" + script[1]).join(script[1]);
4264                //restore unicode chars.
4265                confirmContent = confirmContent.replace(/\\u([\d\w]{4})/gi, function(match, charCode) {
4266                    return String.fromCharCode(parseInt(charCode, 16));
4267                });
4268                instance.attr("onclick", instance.attr("onclick").replace(script[0], "void(0)")).dnnConfirm({
4269                    text: confirmContent,
4270                    isButton: isButton
4271                });
4272            }
4273        });
4274    };
4275    var saveRgDataDivScrollTop = function () {
4276        window.__rgDataDivScrollTopPersistArray = [];
4277        $('.rgDataDiv').each(function () {
4278            var $this = $(this);
4279            var ele = $this.get(0);
4280            if (ele.scrollPane) {
4281                var api = ele.scrollPane.data('jsp');
4282                var y = api.getContentPositionY();
4283                window.__rgDataDivScrollTopPersistArray.push(y);
4284            }
4285        });
4286    };
4287
4288    var handlerSendVerificationMailLink = function() {
4289        $(document.body).on('click', 'a.send-verification-mail', function(e) {
4290            e.preventDefault();
4291
4292            var service = $.dnnSF();
4293            var url = service.getServiceRoot('InternalServices') + 'NewUserNotificationService/SendVerificationMail';
4294            var antiForgeryToken = $('input[name="__RequestVerificationToken"]').val();
4295            url += '?__RequestVerificationToken=' + antiForgeryToken;
4296
4297            $.ajax({
4298                url: url,
4299                beforeSend: service ? service.setModuleHeaders : null,
4300                success: function(data) {
4301                    $.dnnAlert({ text: data.Result });
4302                },
4303                error: function (xhr, textStatus, errorThrown) {
4304                    if (xhr && xhr.responseText) {
4305                        $.dnnAlert({ text: JSON.parse(xhr.responseText).Message });
4306                    }
4307                },
4308                type: 'POST',
4309                dataType: 'json',
4310                contentType: "application/json"
4311            });
4312        });
4313    };
4314
4315    function registerEvents() {
4316        Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(saveRgDataDivScrollTop);
4317        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(dnnInitCustomisedCtrls);
4318    }
4319
4320    window.__rgDataDivScrollTopPersistArray = [];
4321    $(document).ajaxComplete(dnnInitCustomisedCtrls);
4322    $(dnnInitCustomisedCtrls);
4323    $(registerEvents);
4324    handlerSendVerificationMailLink();
4325})(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.