PageSourceSearch

https://nat.go.th/Resources/Shared/Scripts/dnn.jquery.js?cdv=1095

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