PageSourceSearch

https://www.mikesfamous.com/Resources/libraries/DnnPlugins/10_02_01/dnn.jquery.js?cdv=1326

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