Modifications for module installer in openemr.
[openemr.git] / interface / modules / zend_modules / public / js / lib / jquery.custom-scrollbar.js
blob4a0f644d458ec4b11656fc518e57576acd1266dd
1 (function ($) {
3   $.fn.customScrollbar = function (options, args) {
5     var defaultOptions = {
6       skin: undefined,
7       hScroll: true,
8       vScroll: true,
9       updateOnWindowResize: false,
10       animationSpeed: 300,
11       onCustomScroll: undefined
12     }
14     var Scrollable = function (element, options) {
15       this.$element = $(element);
16       this.options = options;
17       this.addScrollableClass();
18       this.addSkinClass();
19       this.addScrollBarComponents();
20       if (this.options.vScroll)
21         this.vScrollbar = new Scrollbar(this, new VSizing());
22       if (this.options.hScroll)
23         this.hScrollbar = new Scrollbar(this, new HSizing());
24       this.$element.data("scrollable", this);
25       this.initKeyboardScrolling();
26       this.bindEvents();
27     }
29     Scrollable.prototype = {
31       addScrollableClass: function () {
32         if (!this.$element.hasClass("scrollable")) {
33           this.scrollableAdded = true;
34           this.$element.addClass("scrollable");
35         }
36       },
38       removeScrollableClass: function () {
39         if (this.scrollableAdded)
40           this.$element.removeClass("scrollable");
41       },
43       addSkinClass: function () {
44         if (typeof(this.options.skin) == "string" && !this.$element.hasClass(this.options.skin)) {
45           this.skinClassAdded = true;
46           this.$element.addClass(this.options.skin);
47         }
48       },
50       removeSkinClass: function () {
51         if (this.skinClassAdded)
52           this.$element.removeClass(this.options.skin);
53       },
55       addScrollBarComponents: function () {
56         this.assignViewPort();
57         if (this.$viewPort.length == 0) {
58           this.$element.wrapInner("<div class=\"viewport\" />");
59           this.assignViewPort();
60           this.viewPortAdded = true;
61         }
62         this.assignOverview();
63         if (this.$overview.length == 0) {
64           this.$viewPort.wrapInner("<div class=\"overview\" />");
65           this.assignOverview();
66           this.overviewAdded = true;
67         }
68         this.addScrollBar("vertical", "prepend");
69         this.addScrollBar("horizontal", "append");
70       },
72       removeScrollbarComponents: function () {
73         this.removeScrollbar("vertical");
74         this.removeScrollbar("horizontal");
75         if (this.overviewAdded)
76           this.$element.unwrap();
77         if (this.viewPortAdded)
78           this.$element.unwrap();
79       },
81       removeScrollbar: function (orientation) {
82         if (this[orientation + "ScrollbarAdded"])
83           this.$element.find(".scroll-bar." + orientation).remove();
84       },
86       assignViewPort: function () {
87         this.$viewPort = this.$element.find(".viewport");
88       },
90       assignOverview: function () {
91         this.$overview = this.$viewPort.find(".overview");
92       },
94       addScrollBar: function (orientation, fun) {
95         if (this.$element.find(".scroll-bar." + orientation).length == 0) {
96           this.$element[fun]("<div class='scroll-bar " + orientation + "'><div class='thumb'></div></div>")
97           this[orientation + "ScrollbarAdded"] = true;
98         }
99       },
101       resize: function (keepPosition) {
102         if (this.vScrollbar)
103           this.vScrollbar.resize(keepPosition);
104         if (this.hScrollbar)
105           this.hScrollbar.resize(keepPosition);
106       },
108       scrollTo: function (element) {
109         if (this.vScrollbar)
110           this.vScrollbar.scrollToElement(element);
111         if (this.hScrollbar)
112           this.hScrollbar.scrollToElement(element);
113       },
115       scrollToXY: function (x, y) {
116         this.scrollToX(x);
117         this.scrollToY(y);
118       },
120       scrollToX: function (x) {
121         if (this.hScrollbar)
122           this.hScrollbar.scrollOverviewTo(x, true);
123       },
125       scrollToY: function (y) {
126         if (this.vScrollbar)
127           this.vScrollbar.scrollOverviewTo(y, true);
128       },
130       remove: function () {
131         this.removeScrollableClass();
132         this.removeSkinClass();
133         this.removeScrollbarComponents();
134         this.$element.data("scrollable", null);
135         this.removeKeyboardScrolling();
136         if (this.vScrollbar)
137           this.vScrollbar.remove();
138         if (this.hScrollbar)
139           this.hScrollbar.remove();
140       },
142       setAnimationSpeed: function (speed) {
143         this.options.animationSpeed = speed;
144       },
146       isInside: function (element, wrappingElement) {
147         var $element = $(element);
148         var $wrappingElement = $(wrappingElement);
149         var elementOffset = $element.offset();
150         var wrappingElementOffset = $wrappingElement.offset();
151         return (elementOffset.top >= wrappingElementOffset.top) && (elementOffset.left >= wrappingElementOffset.left) &&
152           (elementOffset.top + $element.height() <= wrappingElementOffset.top + $wrappingElement.height()) &&
153           (elementOffset.left + $element.width() <= wrappingElementOffset.left + $wrappingElement.width())
154       },
156       initKeyboardScrolling: function () {
157         var _this = this;
159         this.elementKeydown = function (event) {
160           if (document.activeElement === _this.$element[0]) {
161             if (_this.vScrollbar)
162               _this.vScrollbar.keyScroll(event);
163             if (_this.hScrollbar)
164               _this.hScrollbar.keyScroll(event);
165           }
166         }
168         this.$element
169           .attr('tabindex', '-1')
170           .keydown(this.elementKeydown);
171       },
173       removeKeyboardScrolling: function () {
174         this.$element
175           .removeAttr('tabindex')
176           .unbind("keydown", this.elementKeydown);
177       },
179       bindEvents: function () {
180         if (this.options.onCustomScroll)
181           this.$element.on("customScroll", this.options.onCustomScroll);
182       }
184     }
186     var Scrollbar = function (scrollable, sizing) {
187       this.scrollable = scrollable;
188       this.sizing = sizing
189       this.$scrollBar = this.sizing.scrollBar(this.scrollable.$element);
190       this.$thumb = this.$scrollBar.find(".thumb");
191       this.setScrollPosition(0, 0);
192       this.resize();
193       this.initMouseMoveScrolling();
194       this.initMouseWheelScrolling();
195       this.initTouchScrolling();
196       this.initMouseClickScrolling();
197       this.initWindowResize();
198     }
200     Scrollbar.prototype = {
202       resize: function (keepPosition) {
203         this.scrollable.$viewPort.height(this.scrollable.$element.height());
204         this.sizing.size(this.scrollable.$viewPort, this.sizing.size(this.scrollable.$element));
205         this.viewPortSize = this.sizing.size(this.scrollable.$viewPort);
206         this.overviewSize = this.sizing.size(this.scrollable.$overview);
207         this.ratio = this.viewPortSize / this.overviewSize;
208         this.sizing.size(this.$scrollBar, this.viewPortSize);
209         this.thumbSize = Math.max(Math.round(this.ratio * this.viewPortSize), this.sizing.minSize(this.$thumb));
210         this.sizing.size(this.$thumb, this.thumbSize);
211         this.maxThumbPosition = this.calculateMaxThumbPosition();
212         this.maxOverviewPosition = this.calculateMaxOverviewPosition();
213         this.enabled = (this.overviewSize > this.viewPortSize);
214         if (this.scrollPercent === undefined)
215           this.scrollPercent = 0.0;
216         if (this.enabled)
217           this.rescroll(keepPosition);
218         else
219           this.setScrollPosition(0, 0);
220         this.$scrollBar.toggle(this.enabled);
221       },
223       initMouseMoveScrolling: function () {
224         var _this = this;
225         this.$thumb.mousedown(function (event) {
226           if (_this.enabled)
227             _this.startMouseMoveScrolling(event);
228         });
229         this.documentMouseup = function (event) {
230           _this.stopMouseMoveScrolling(event);
231         };
232         $(document).mouseup(this.documentMouseup);
233         this.documentMousemove = function (event) {
234           _this.mouseMoveScroll(event);
235         };
236         $(document).mousemove(this.documentMousemove);
237         this.$thumb.click(function (event) {
238           event.stopPropagation();
239         });
240       },
242       removeMouseMoveScrolling: function () {
243         this.$thumb.unbind();
244         $(document).unbind("mouseup", this.documentMouseup);
245         $(document).unbind("mousemove", this.documentMousemove);
246       },
248       initMouseWheelScrolling: function () {
249         var _this = this;
250         this.scrollable.$element.mousewheel(function (event, delta, deltaX, deltaY) {
251           if (_this.enabled) {
252             _this.mouseWheelScroll(deltaX, deltaY);
253             return false;
254           }
255         });
256       },
258       removeMouseWheelScrolling: function () {
259         this.scrollable.$element.unbind("mousewheel");
260       },
262       initTouchScrolling: function () {
263         if (document.addEventListener) {
264           var _this = this;
265           this.elementTouchstart = function (event) {
266             if (_this.enabled)
267               _this.startTouchScrolling(event);
268           }
269           this.scrollable.$element[0].addEventListener("touchstart", this.elementTouchstart);
270           this.documentTouchmove = function (event) {
271             _this.touchScroll(event);
272           }
273           document.addEventListener("touchmove", this.documentTouchmove);
274           this.elementTouchend = function (event) {
275             _this.stopTouchScrolling(event);
276           }
277           this.scrollable.$element[0].addEventListener("touchend", this.elementTouchend);
278         }
279       },
281       removeTouchScrolling: function () {
282         if (document.addEventListener) {
283           this.scrollable.$element[0].removeEventListener("touchstart", this.elementTouchstart);
284           document.removeEventListener("touchmove", this.documentTouchmove);
285           this.scrollable.$element[0].removeEventListener("touchend", this.elementTouchend);
286         }
287       },
289       initMouseClickScrolling: function () {
290         var _this = this;
291         this.scrollBarClick = function (event) {
292           _this.mouseClickScroll(event);
293         };
294         this.$scrollBar.click(this.scrollBarClick);
295       },
297       removeMouseClickScrolling: function () {
298         this.$scrollBar.unbind("click", this.scrollBarClick);
299       },
301       initWindowResize: function () {
302         if (this.scrollable.options.updateOnWindowResize) {
303           var _this = this;
304           this.windowResize = function () {
305             _this.resize();
306           };
307           $(window).resize(this.windowResize);
308         }
309       },
311       removeWindowResize: function () {
312         $(window).unbind("resize", this.windowResize);
313       },
315       isKeyScrolling: function (key) {
316         return this.keyScrollDelta(key) != null;
317       },
319       keyScrollDelta: function (key) {
320         for (var scrollingKey in this.sizing.scrollingKeys)
321           if (scrollingKey == key)
322             return this.sizing.scrollingKeys[key](this.viewPortSize);
323         return null;
324       },
326       startMouseMoveScrolling: function (event) {
327         this.mouseMoveScrolling = true;
328         $("html").addClass("not-selectable");
329         this.setUnselectable($("html"), "on");
330         this.setScrollEvent(event);
331       },
333       stopMouseMoveScrolling: function (event) {
334         this.mouseMoveScrolling = false;
335         $("html").removeClass("not-selectable");
336         this.setUnselectable($("html"), null);
337       },
339       setUnselectable: function (element, value) {
340         if (element.attr("unselectable") != value) {
341           element.attr("unselectable", value);
342           element.find(':not(input)').attr('unselectable', value);
343         }
344       },
346       mouseMoveScroll: function (event) {
347         if (this.mouseMoveScrolling) {
348           var delta = this.sizing.mouseDelta(this.scrollEvent, event);
349           this.scrollThumbBy(delta);
350           this.setScrollEvent(event);
351         }
352       },
354       startTouchScrolling: function (event) {
355         if (event.touches && event.touches.length == 1) {
356           this.setScrollEvent(event.touches[0]);
357           this.touchScrolling = true;
358           event.stopPropagation();
359         }
360       },
362       touchScroll: function (event) {
363         if (this.touchScrolling && event.touches && event.touches.length == 1) {
364           var delta = -this.sizing.mouseDelta(this.scrollEvent, event.touches[0]);
365           this.scrollOverviewBy(delta);
366           this.setScrollEvent(event.touches[0]);
367           event.stopPropagation();
368           event.preventDefault();
369         }
370       },
372       stopTouchScrolling: function (event) {
373         this.touchScrolling = false;
374         event.stopPropagation();
375       },
377       mouseWheelScroll: function (deltaX, deltaY) {
378         var delta = this.sizing.wheelDelta(deltaX, deltaY) * -10;
379         if (delta != 0)
380           this.scrollThumbBy(delta);
381       },
383       mouseClickScroll: function (event) {
384         var delta = this.viewPortSize - 20;
385         if (event["page" + this.sizing.scrollAxis()] < this.$thumb.offset()[this.sizing.offsetComponent()])
386         // mouse click over thumb
387           delta = -delta;
388         this.scrollOverviewBy(delta);
389       },
391       keyScroll: function (event) {
392         var keyDown = event.which;
393         if (this.enabled && this.isKeyScrolling(keyDown)) {
394           this.scrollOverviewBy(this.keyScrollDelta(keyDown));
395           event.preventDefault();
396         }
397       },
399       scrollThumbBy: function (delta) {
400         var thumbPosition = this.thumbPosition();
401         thumbPosition += delta;
402         thumbPosition = this.positionOrMax(thumbPosition, this.maxThumbPosition);
403         var oldScrollPercent = this.scrollPercent;
404         this.scrollPercent = thumbPosition / this.maxThumbPosition;
405         var overviewPosition = (thumbPosition * this.maxOverviewPosition) / this.maxThumbPosition;
406         this.setScrollPosition(overviewPosition, thumbPosition);
407         if (oldScrollPercent != this.scrollPercent)
408           this.triggerCustomScroll(oldScrollPercent);
409       },
411       thumbPosition: function () {
412         return this.$thumb.position()[this.sizing.offsetComponent()];
413       },
415       scrollOverviewBy: function (delta) {
416         var overviewPosition = this.overviewPosition() + delta;
417         this.scrollOverviewTo(overviewPosition, false);
418       },
420       overviewPosition: function () {
421         return -this.scrollable.$overview.position()[this.sizing.offsetComponent()];
422       },
424       scrollOverviewTo: function (overviewPosition, animate) {
425         overviewPosition = this.positionOrMax(overviewPosition, this.maxOverviewPosition);
426         var oldScrollPercent = this.scrollPercent;
427         this.scrollPercent = overviewPosition / this.maxOverviewPosition;
428         var thumbPosition = this.scrollPercent * this.maxThumbPosition;
429         if (animate)
430           this.setScrollPositionWithAnimation(overviewPosition, thumbPosition);
431         else
432           this.setScrollPosition(overviewPosition, thumbPosition);
433         if (oldScrollPercent != this.scrollPercent)
434           this.triggerCustomScroll(oldScrollPercent);
435       },
437       positionOrMax: function (p, max) {
438         if (p < 0)
439           return 0;
440         else if (p > max)
441           return max;
442         else
443           return p;
444       },
446       triggerCustomScroll: function (oldScrollPercent) {
447         this.scrollable.$element.trigger("customScroll", {
448             scrollAxis: this.sizing.scrollAxis(),
449             direction: this.sizing.scrollDirection(oldScrollPercent, this.scrollPercent),
450             scrollPercent: this.scrollPercent * 100
451           }
452         );
453       },
455       rescroll: function (keepPosition) {
456         if (keepPosition) {
457           var overviewPosition = this.positionOrMax(this.overviewPosition(), this.maxOverviewPosition);
458           this.scrollPercent = overviewPosition / this.maxOverviewPosition;
459           var thumbPosition = this.scrollPercent * this.maxThumbPosition;
460           this.setScrollPosition(overviewPosition, thumbPosition);
461         }
462         else {
463           var thumbPosition = this.scrollPercent * this.maxThumbPosition;
464           var overviewPosition = this.scrollPercent * this.maxOverviewPosition;
465           this.setScrollPosition(overviewPosition, thumbPosition);
466         }
467       },
469       setScrollPosition: function (overviewPosition, thumbPosition) {
470         this.$thumb.css(this.sizing.offsetComponent(), thumbPosition + "px");
471         this.scrollable.$overview.css(this.sizing.offsetComponent(), -overviewPosition + "px");
472       },
474       setScrollPositionWithAnimation: function (overviewPosition, thumbPosition) {
475         var thumbAnimationOpts = {};
476         var overviewAnimationOpts = {};
477         thumbAnimationOpts[this.sizing.offsetComponent()] = thumbPosition + "px";
478         this.$thumb.animate(thumbAnimationOpts, this.scrollable.options.animationSpeed);
479         overviewAnimationOpts[this.sizing.offsetComponent()] = -overviewPosition + "px";
480         this.scrollable.$overview.animate(overviewAnimationOpts, this.scrollable.options.animationSpeed);
481       },
483       calculateMaxThumbPosition: function () {
484         return this.sizing.size(this.$scrollBar) - this.thumbSize;
485       },
487       calculateMaxOverviewPosition: function () {
488         return this.sizing.size(this.scrollable.$overview) - this.sizing.size(this.scrollable.$viewPort);
489       },
491       setScrollEvent: function (event) {
492         var attr = "page" + this.sizing.scrollAxis();
493         if (!this.scrollEvent || this.scrollEvent[attr] != event[attr])
494           this.scrollEvent = {pageX: event.pageX, pageY: event.pageY};
495       },
497       scrollToElement: function (element) {
498         var $element = $(element);
499         if (this.sizing.isInside($element, this.scrollable.$overview) && !this.sizing.isInside($element, this.scrollable.$viewPort)) {
500           var elementOffset = $element.offset();
501           var overviewOffset = this.scrollable.$overview.offset();
502           var viewPortOffset = this.scrollable.$viewPort.offset();
503           this.scrollOverviewTo(elementOffset[this.sizing.offsetComponent()] - overviewOffset[this.sizing.offsetComponent()], true);
504         }
505       },
507       remove: function () {
508         this.removeMouseMoveScrolling();
509         this.removeMouseWheelScrolling();
510         this.removeTouchScrolling();
511         this.removeMouseClickScrolling();
512         this.removeWindowResize();
513       }
515     }
517     var HSizing = function () {
518     }
520     HSizing.prototype = {
521       size: function ($el, arg) {
522         if (arg)
523           return $el.width(arg);
524         else
525           return $el.width();
526       },
528       minSize: function ($el) {
529         return parseInt($el.css("min-width")) || 0;
530       },
532       scrollBar: function ($el) {
533         return $el.find(".scroll-bar.horizontal");
534       },
536       mouseDelta: function (event1, event2) {
537         return event2.pageX - event1.pageX;
538       },
540       offsetComponent: function () {
541         return "left";
542       },
544       wheelDelta: function (deltaX, deltaY) {
545         return deltaX;
546       },
548       scrollAxis: function () {
549         return "X";
550       },
552       scrollDirection: function (oldPercent, newPercent) {
553         return oldPercent < newPercent ? "right" : "left";
554       },
556       scrollingKeys: {
557         37: function (viewPortSize) {
558           return -10; //arrow left
559         },
560         39: function (viewPortSize) {
561           return 10; //arrow right
562         }
563       },
565       isInside: function (element, wrappingElement) {
566         var $element = $(element);
567         var $wrappingElement = $(wrappingElement);
568         var elementOffset = $element.offset();
569         var wrappingElementOffset = $wrappingElement.offset();
570         return (elementOffset.left >= wrappingElementOffset.left) &&
571           (elementOffset.left + $element.width() <= wrappingElementOffset.left + $wrappingElement.width());
572       }
574     }
576     var VSizing = function () {
577     }
579     VSizing.prototype = {
581       size: function ($el, arg) {
582         if (arg)
583           return $el.height(arg);
584         else
585           return $el.height();
586       },
588       minSize: function ($el) {
589         return parseInt($el.css("min-height")) || 0;
590       },
592       scrollBar: function ($el) {
593         return $el.find(".scroll-bar.vertical");
594       },
596       mouseDelta: function (event1, event2) {
597         return event2.pageY - event1.pageY;
598       },
600       offsetComponent: function () {
601         return "top";
602       },
604       wheelDelta: function (deltaX, deltaY) {
605         return deltaY;
606       },
608       scrollAxis: function () {
609         return "Y";
610       },
612       scrollDirection: function (oldPercent, newPercent) {
613         return oldPercent < newPercent ? "down" : "up";
614       },
616       scrollingKeys: {
617         38: function (viewPortSize) {
618           return -10; //arrow up
619         },
620         40: function (viewPortSize) {
621           return 10; //arrow down
622         },
623         33: function (viewPortSize) {
624           return -(viewPortSize - 20); //page up
625         },
626         34: function (viewPortSize) {
627           return viewPortSize - 20; //page down
628         }
629       },
631       isInside: function (element, wrappingElement) {
632         var $element = $(element);
633         var $wrappingElement = $(wrappingElement);
634         var elementOffset = $element.offset();
635         var wrappingElementOffset = $wrappingElement.offset();
636         return (elementOffset.top >= wrappingElementOffset.top) &&
637           (elementOffset.top + $element.height() <= wrappingElementOffset.top + $wrappingElement.height());
638       }
640     }
642     return this.each(function () {
643       if (options == undefined)
644         options = defaultOptions;
645       if (typeof(options) == "string") {
646         var scrollable = $(this).data("scrollable");
647         if (scrollable)
648           scrollable[options](args);
649       }
650       else if (typeof(options) == "object") {
651         options = $.extend(defaultOptions, options);
652         new Scrollable($(this), options);
653       }
654       else
655         throw "Invalid type of options";
656     });
658   }
659   ;
662   (jQuery);
664 (function ($) {
666   var types = ['DOMMouseScroll', 'mousewheel'];
668   if ($.event.fixHooks) {
669     for (var i = types.length; i;) {
670       $.event.fixHooks[ types[--i] ] = $.event.mouseHooks;
671     }
672   }
674   $.event.special.mousewheel = {
675     setup: function () {
676       if (this.addEventListener) {
677         for (var i = types.length; i;) {
678           this.addEventListener(types[--i], handler, false);
679         }
680       } else {
681         this.onmousewheel = handler;
682       }
683     },
685     teardown: function () {
686       if (this.removeEventListener) {
687         for (var i = types.length; i;) {
688           this.removeEventListener(types[--i], handler, false);
689         }
690       } else {
691         this.onmousewheel = null;
692       }
693     }
694   };
696   $.fn.extend({
697     mousewheel: function (fn) {
698       return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
699     },
701     unmousewheel: function (fn) {
702       return this.unbind("mousewheel", fn);
703     }
704   });
707   function handler(event) {
708     var orgEvent = event || window.event, args = [].slice.call(arguments, 1), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
709     event = $.event.fix(orgEvent);
710     event.type = "mousewheel";
712     // Old school scrollwheel delta
713     if (orgEvent.wheelDelta) {
714       delta = orgEvent.wheelDelta / 120;
715     }
716     if (orgEvent.detail) {
717       delta = -orgEvent.detail / 3;
718     }
720     // New school multidimensional scroll (touchpads) deltas
721     deltaY = delta;
723     // Gecko
724     if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
725       deltaY = 0;
726       deltaX = delta;
727     }
729     // Webkit
730     if (orgEvent.wheelDeltaY !== undefined) {
731       deltaY = orgEvent.wheelDeltaY / 120;
732     }
733     if (orgEvent.wheelDeltaX !== undefined) {
734       deltaX = orgEvent.wheelDeltaX / 120;
735     }
737     // Add event and delta to the front of the arguments
738     args.unshift(event, delta, deltaX, deltaY);
740     return ($.event.dispatch || $.event.handle).apply(this, args);
741   }
743 })(jQuery);