PageSourceSearch

https://www.kester.com/Resources/Shared/Scripts/dnn.jquery.js?cdv=363

js kester.com collected 2026-09-24 21:21:54 UTC 175,176 bytes, 4,323 lines download raw bytes

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