summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2016-01-23 17:44:40 -0800
committerRobert Speicher <rspeicher@gmail.com>2016-01-23 17:45:39 -0800
commitd66826630614c9b47f2062e3d2c98ad519d31ce4 (patch)
treede4243517aabc9df92bb9a28b2cee7b28e2d8d75
parent5409fc49bd7fb1e24f048ec5b8931b216b6ceda8 (diff)
parent82a3cfc151c4c96935387be3e94f703beb449b25 (diff)
downloadgitlab-ce-d66826630614c9b47f2062e3d2c98ad519d31ce4.tar.gz
Merge branch 'rs-no-minified-js'
Don't vendor minified JS Fixes #4031 See merge request !2494
-rw-r--r--CHANGELOG1
-rw-r--r--app/assets/javascripts/application.js.coffee10
-rwxr-xr-xvendor/assets/javascripts/Chart.js3477
-rw-r--r--vendor/assets/javascripts/chart-lib.min.js11
-rw-r--r--vendor/assets/javascripts/fuzzaldrin-plus.js1161
-rw-r--r--vendor/assets/javascripts/fuzzaldrin-plus.min.js1
-rw-r--r--vendor/assets/javascripts/g.bar-min.js8
-rw-r--r--vendor/assets/javascripts/g.bar.js674
-rw-r--r--vendor/assets/javascripts/g.raphael-min.js7
-rw-r--r--vendor/assets/javascripts/g.raphael.js861
-rw-r--r--vendor/assets/javascripts/jquery.nicescroll.js3634
-rw-r--r--vendor/assets/javascripts/jquery.nicescroll.min.js118
12 files changed, 9813 insertions, 150 deletions
diff --git a/CHANGELOG b/CHANGELOG
index d78c38cf1dc..b3b4aa380d5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,7 @@ v 8.5.0 (unreleased)
- New UI for pagination
- Fix diff comments loaded by AJAX to load comment with diff in discussion tab
- Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel)
+ - Don't vendor minified JS
v 8.4.0
- Allow LDAP users to change their email if it was not set by the LDAP server
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index c095e5ae2b1..eb18d32b25c 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -21,9 +21,9 @@
#= require bootstrap
#= require select2
#= require raphael
-#= require g.raphael-min
-#= require g.bar-min
-#= require chart-lib.min
+#= require g.raphael
+#= require g.bar
+#= require Chart
#= require branch-graph
#= require ace/ace
#= require ace/ext-searchbox
@@ -38,9 +38,9 @@
#= require shortcuts_dashboard_navigation
#= require shortcuts_issuable
#= require shortcuts_network
-#= require jquery.nicescroll.min
+#= require jquery.nicescroll
#= require_tree .
-#= require fuzzaldrin-plus.min
+#= require fuzzaldrin-plus
window.slugify = (text) ->
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
diff --git a/vendor/assets/javascripts/Chart.js b/vendor/assets/javascripts/Chart.js
new file mode 100755
index 00000000000..c264262ba73
--- /dev/null
+++ b/vendor/assets/javascripts/Chart.js
@@ -0,0 +1,3477 @@
+/*!
+ * Chart.js
+ * http://chartjs.org/
+ * Version: 1.0.2
+ *
+ * Copyright 2015 Nick Downie
+ * Released under the MIT license
+ * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
+ */
+
+
+(function(){
+
+ "use strict";
+
+ //Declare root variable - window in the browser, global on the server
+ var root = this,
+ previous = root.Chart;
+
+ //Occupy the global variable of Chart, and create a simple base class
+ var Chart = function(context){
+ var chart = this;
+ this.canvas = context.canvas;
+
+ this.ctx = context;
+
+ //Variables global to the chart
+ var computeDimension = function(element,dimension)
+ {
+ if (element['offset'+dimension])
+ {
+ return element['offset'+dimension];
+ }
+ else
+ {
+ return document.defaultView.getComputedStyle(element).getPropertyValue(dimension);
+ }
+ }
+
+ var width = this.width = computeDimension(context.canvas,'Width');
+ var height = this.height = computeDimension(context.canvas,'Height');
+
+ // Firefox requires this to work correctly
+ context.canvas.width = width;
+ context.canvas.height = height;
+
+ var width = this.width = context.canvas.width;
+ var height = this.height = context.canvas.height;
+ this.aspectRatio = this.width / this.height;
+ //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
+ helpers.retinaScale(this);
+
+ return this;
+ };
+ //Globally expose the defaults to allow for user updating/changing
+ Chart.defaults = {
+ global: {
+ // Boolean - Whether to animate the chart
+ animation: true,
+
+ // Number - Number of animation steps
+ animationSteps: 60,
+
+ // String - Animation easing effect
+ animationEasing: "easeOutQuart",
+
+ // Boolean - If we should show the scale at all
+ showScale: true,
+
+ // Boolean - If we want to override with a hard coded scale
+ scaleOverride: false,
+
+ // ** Required if scaleOverride is true **
+ // Number - The number of steps in a hard coded scale
+ scaleSteps: null,
+ // Number - The value jump in the hard coded scale
+ scaleStepWidth: null,
+ // Number - The scale starting value
+ scaleStartValue: null,
+
+ // String - Colour of the scale line
+ scaleLineColor: "rgba(0,0,0,.1)",
+
+ // Number - Pixel width of the scale line
+ scaleLineWidth: 1,
+
+ // Boolean - Whether to show labels on the scale
+ scaleShowLabels: true,
+
+ // Interpolated JS string - can access value
+ scaleLabel: "<%=value%>",
+
+ // Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there
+ scaleIntegersOnly: true,
+
+ // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
+ scaleBeginAtZero: false,
+
+ // String - Scale label font declaration for the scale label
+ scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
+
+ // Number - Scale label font size in pixels
+ scaleFontSize: 12,
+
+ // String - Scale label font weight style
+ scaleFontStyle: "normal",
+
+ // String - Scale label font colour
+ scaleFontColor: "#666",
+
+ // Boolean - whether or not the chart should be responsive and resize when the browser does.
+ responsive: false,
+
+ // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
+ maintainAspectRatio: true,
+
+ // Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
+ showTooltips: true,
+
+ // Boolean - Determines whether to draw built-in tooltip or call custom tooltip function
+ customTooltips: false,
+
+ // Array - Array of string names to attach tooltip events
+ tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
+
+ // String - Tooltip background colour
+ tooltipFillColor: "rgba(0,0,0,0.8)",
+
+ // String - Tooltip label font declaration for the scale label
+ tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
+
+ // Number - Tooltip label font size in pixels
+ tooltipFontSize: 14,
+
+ // String - Tooltip font weight style
+ tooltipFontStyle: "normal",
+
+ // String - Tooltip label font colour
+ tooltipFontColor: "#fff",
+
+ // String - Tooltip title font declaration for the scale label
+ tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
+
+ // Number - Tooltip title font size in pixels
+ tooltipTitleFontSize: 14,
+
+ // String - Tooltip title font weight style
+ tooltipTitleFontStyle: "bold",
+
+ // String - Tooltip title font colour
+ tooltipTitleFontColor: "#fff",
+
+ // Number - pixel width of padding around tooltip text
+ tooltipYPadding: 6,
+
+ // Number - pixel width of padding around tooltip text
+ tooltipXPadding: 6,
+
+ // Number - Size of the caret on the tooltip
+ tooltipCaretSize: 8,
+
+ // Number - Pixel radius of the tooltip border
+ tooltipCornerRadius: 6,
+
+ // Number - Pixel offset from point x to tooltip edge
+ tooltipXOffset: 10,
+
+ // String - Template string for single tooltips
+ tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
+
+ // String - Template string for single tooltips
+ multiTooltipTemplate: "<%= value %>",
+
+ // String - Colour behind the legend colour block
+ multiTooltipKeyBackground: '#fff',
+
+ // Function - Will fire on animation progression.
+ onAnimationProgress: function(){},
+
+ // Function - Will fire on animation completion.
+ onAnimationComplete: function(){}
+
+ }
+ };
+
+ //Create a dictionary of chart types, to allow for extension of existing types
+ Chart.types = {};
+
+ //Global Chart helpers object for utility methods and classes
+ var helpers = Chart.helpers = {};
+
+ //-- Basic js utility methods
+ var each = helpers.each = function(loopable,callback,self){
+ var additionalArgs = Array.prototype.slice.call(arguments, 3);
+ // Check to see if null or undefined firstly.
+ if (loopable){
+ if (loopable.length === +loopable.length){
+ var i;
+ for (i=0; i<loopable.length; i++){
+ callback.apply(self,[loopable[i], i].concat(additionalArgs));
+ }
+ }
+ else{
+ for (var item in loopable){
+ callback.apply(self,[loopable[item],item].concat(additionalArgs));
+ }
+ }
+ }
+ },
+ clone = helpers.clone = function(obj){
+ var objClone = {};
+ each(obj,function(value,key){
+ if (obj.hasOwnProperty(key)) objClone[key] = value;
+ });
+ return objClone;
+ },
+ extend = helpers.extend = function(base){
+ each(Array.prototype.slice.call(arguments,1), function(extensionObject) {
+ each(extensionObject,function(value,key){
+ if (extensionObject.hasOwnProperty(key)) base[key] = value;
+ });
+ });
+ return base;
+ },
+ merge = helpers.merge = function(base,master){
+ //Merge properties in left object over to a shallow clone of object right.
+ var args = Array.prototype.slice.call(arguments,0);
+ args.unshift({});
+ return extend.apply(null, args);
+ },
+ indexOf = helpers.indexOf = function(arrayToSearch, item){
+ if (Array.prototype.indexOf) {
+ return arrayToSearch.indexOf(item);
+ }
+ else{
+ for (var i = 0; i < arrayToSearch.length; i++) {
+ if (arrayToSearch[i] === item) return i;
+ }
+ return -1;
+ }
+ },
+ where = helpers.where = function(collection, filterCallback){
+ var filtered = [];
+
+ helpers.each(collection, function(item){
+ if (filterCallback(item)){
+ filtered.push(item);
+ }
+ });
+
+ return filtered;
+ },
+ findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){
+ // Default to start of the array
+ if (!startIndex){
+ startIndex = -1;
+ }
+ for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
+ var currentItem = arrayToSearch[i];
+ if (filterCallback(currentItem)){
+ return currentItem;
+ }
+ }
+ },
+ findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){
+ // Default to end of the array
+ if (!startIndex){
+ startIndex = arrayToSearch.length;
+ }
+ for (var i = startIndex - 1; i >= 0; i--) {
+ var currentItem = arrayToSearch[i];
+ if (filterCallback(currentItem)){
+ return currentItem;
+ }
+ }
+ },
+ inherits = helpers.inherits = function(extensions){
+ //Basic javascript inheritance based on the model created in Backbone.js
+ var parent = this;
+ var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };
+
+ var Surrogate = function(){ this.constructor = ChartElement;};
+ Surrogate.prototype = parent.prototype;
+ ChartElement.prototype = new Surrogate();
+
+ ChartElement.extend = inherits;
+
+ if (extensions) extend(ChartElement.prototype, extensions);
+
+ ChartElement.__super__ = parent.prototype;
+
+ return ChartElement;
+ },
+ noop = helpers.noop = function(){},
+ uid = helpers.uid = (function(){
+ var id=0;
+ return function(){
+ return "chart-" + id++;
+ };
+ })(),
+ warn = helpers.warn = function(str){
+ //Method for warning of errors
+ if (window.console && typeof window.console.warn == "function") console.warn(str);
+ },
+ amd = helpers.amd = (typeof define == 'function' && define.amd),
+ //-- Math methods
+ isNumber = helpers.isNumber = function(n){
+ return !isNaN(parseFloat(n)) && isFinite(n);
+ },
+ max = helpers.max = function(array){
+ return Math.max.apply( Math, array );
+ },
+ min = helpers.min = function(array){
+ return Math.min.apply( Math, array );
+ },
+ cap = helpers.cap = function(valueToCap,maxValue,minValue){
+ if(isNumber(maxValue)) {
+ if( valueToCap > maxValue ) {
+ return maxValue;
+ }
+ }
+ else if(isNumber(minValue)){
+ if ( valueToCap < minValue ){
+ return minValue;
+ }
+ }
+ return valueToCap;
+ },
+ getDecimalPlaces = helpers.getDecimalPlaces = function(num){
+ if (num%1!==0 && isNumber(num)){
+ return num.toString().split(".")[1].length;
+ }
+ else {
+ return 0;
+ }
+ },
+ toRadians = helpers.radians = function(degrees){
+ return degrees * (Math.PI/180);
+ },
+ // Gets the angle from vertical upright to the point about a centre.
+ getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){
+ var distanceFromXCenter = anglePoint.x - centrePoint.x,
+ distanceFromYCenter = anglePoint.y - centrePoint.y,
+ radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
+
+
+ var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);
+
+ //If the segment is in the top left quadrant, we need to add another rotation to the angle
+ if (distanceFromXCenter < 0 && distanceFromYCenter < 0){
+ angle += Math.PI*2;
+ }
+
+ return {
+ angle: angle,
+ distance: radialDistanceFromCenter
+ };
+ },
+ aliasPixel = helpers.aliasPixel = function(pixelWidth){
+ return (pixelWidth % 2 === 0) ? 0 : 0.5;
+ },
+ splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){
+ //Props to Rob Spencer at scaled innovation for his post on splining between points
+ //http://scaledinnovation.com/analytics/splines/aboutSplines.html
+ var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),
+ d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),
+ fa=t*d01/(d01+d12),// scaling factor for triangle Ta
+ fb=t*d12/(d01+d12);
+ return {
+ inner : {
+ x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),
+ y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)
+ },
+ outer : {
+ x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),
+ y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)
+ }
+ };
+ },
+ calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){
+ return Math.floor(Math.log(val) / Math.LN10);
+ },
+ calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){
+
+ //Set a minimum step of two - a point at the top of the graph, and a point at the base
+ var minSteps = 2,
+ maxSteps = Math.floor(drawingSize/(textSize * 1.5)),
+ skipFitting = (minSteps >= maxSteps);
+
+ var maxValue = max(valuesArray),
+ minValue = min(valuesArray);
+
+ // We need some degree of seperation here to calculate the scales if all the values are the same
+ // Adding/minusing 0.5 will give us a range of 1.
+ if (maxValue === minValue){
+ maxValue += 0.5;
+ // So we don't end up with a graph with a negative start value if we've said always start from zero
+ if (minValue >= 0.5 && !startFromZero){
+ minValue -= 0.5;
+ }
+ else{
+ // Make up a whole number above the values
+ maxValue += 0.5;
+ }
+ }
+
+ var valueRange = Math.abs(maxValue - minValue),
+ rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),
+ graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
+ graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
+ graphRange = graphMax - graphMin,
+ stepValue = Math.pow(10, rangeOrderOfMagnitude),
+ numberOfSteps = Math.round(graphRange / stepValue);
+
+ //If we have more space on the graph we'll use it to give more definition to the data
+ while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {
+ if(numberOfSteps > maxSteps){
+ stepValue *=2;
+ numberOfSteps = Math.round(graphRange/stepValue);
+ // Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.
+ if (numberOfSteps % 1 !== 0){
+ skipFitting = true;
+ }
+ }
+ //We can fit in double the amount of scale points on the scale
+ else{
+ //If user has declared ints only, and the step value isn't a decimal
+ if (integersOnly && rangeOrderOfMagnitude >= 0){
+ //If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float
+ if(stepValue/2 % 1 === 0){
+ stepValue /=2;
+ numberOfSteps = Math.round(graphRange/stepValue);
+ }
+ //If it would make it a float break out of the loop
+ else{
+ break;
+ }
+ }
+ //If the scale doesn't have to be an int, make the scale more granular anyway.
+ else{
+ stepValue /=2;
+ numberOfSteps = Math.round(graphRange/stepValue);
+ }
+
+ }
+ }
+
+ if (skipFitting){
+ numberOfSteps = minSteps;
+ stepValue = graphRange / numberOfSteps;
+ }
+
+ return {
+ steps : numberOfSteps,
+ stepValue : stepValue,
+ min : graphMin,
+ max : graphMin + (numberOfSteps * stepValue)
+ };
+
+ },
+ /* jshint ignore:start */
+ // Blows up jshint errors based on the new Function constructor
+ //Templating methods
+ //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
+ template = helpers.template = function(templateString, valuesObject){
+
+ // If templateString is function rather than string-template - call the function for valuesObject
+
+ if(templateString instanceof Function){
+ return templateString(valuesObject);
+ }
+
+ var cache = {};
+ function tmpl(str, data){
+ // Figure out if we're getting a template, or if we need to
+ // load the template - and be sure to cache the result.
+ var fn = !/\W/.test(str) ?
+ cache[str] = cache[str] :
+
+ // Generate a reusable function that will serve as a template
+ // generator (and which will be cached).
+ new Function("obj",
+ "var p=[],print=function(){p.push.apply(p,arguments);};" +
+
+ // Introduce the data as local variables using with(){}
+ "with(obj){p.push('" +
+
+ // Convert the template into pure JavaScript
+ str
+ .replace(/[\r\t\n]/g, " ")
+ .split("<%").join("\t")
+ .replace(/((^|%>)[^\t]*)'/g, "$1\r")
+ .replace(/\t=(.*?)%>/g, "',$1,'")
+ .split("\t").join("');")
+ .split("%>").join("p.push('")
+ .split("\r").join("\\'") +
+ "');}return p.join('');"
+ );
+
+ // Provide some basic currying to the user
+ return data ? fn( data ) : fn;
+ }
+ return tmpl(templateString,valuesObject);
+ },
+ /* jshint ignore:end */
+ generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){
+ var labelsArray = new Array(numberOfSteps);
+ if (labelTemplateString){
+ each(labelsArray,function(val,index){
+ labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});
+ });
+ }
+ return labelsArray;
+ },
+ //--Animation methods
+ //Easing functions adapted from Robert Penner's easing equations
+ //http://www.robertpenner.com/easing/
+ easingEffects = helpers.easingEffects = {
+ linear: function (t) {
+ return t;
+ },
+ easeInQuad: function (t) {
+ return t * t;
+ },
+ easeOutQuad: function (t) {
+ return -1 * t * (t - 2);
+ },
+ easeInOutQuad: function (t) {
+ if ((t /= 1 / 2) < 1) return 1 / 2 * t * t;
+ return -1 / 2 * ((--t) * (t - 2) - 1);
+ },
+ easeInCubic: function (t) {
+ return t * t * t;
+ },
+ easeOutCubic: function (t) {
+ return 1 * ((t = t / 1 - 1) * t * t + 1);
+ },
+ easeInOutCubic: function (t) {
+ if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;
+ return 1 / 2 * ((t -= 2) * t * t + 2);
+ },
+ easeInQuart: function (t) {
+ return t * t * t * t;
+ },
+ easeOutQuart: function (t) {
+ return -1 * ((t = t / 1 - 1) * t * t * t - 1);
+ },
+ easeInOutQuart: function (t) {
+ if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;
+ return -1 / 2 * ((t -= 2) * t * t * t - 2);
+ },
+ easeInQuint: function (t) {
+ return 1 * (t /= 1) * t * t * t * t;
+ },
+ easeOutQuint: function (t) {
+ return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
+ },
+ easeInOutQuint: function (t) {
+ if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;
+ return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
+ },
+ easeInSine: function (t) {
+ return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
+ },
+ easeOutSine: function (t) {
+ return 1 * Math.sin(t / 1 * (Math.PI / 2));
+ },
+ easeInOutSine: function (t) {
+ return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
+ },
+ easeInExpo: function (t) {
+ return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
+ },
+ easeOutExpo: function (t) {
+ return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
+ },
+ easeInOutExpo: function (t) {
+ if (t === 0) return 0;
+ if (t === 1) return 1;
+ if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));
+ return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
+ },
+ easeInCirc: function (t) {
+ if (t >= 1) return t;
+ return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
+ },
+ easeOutCirc: function (t) {
+ return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
+ },
+ easeInOutCirc: function (t) {
+ if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
+ return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
+ },
+ easeInElastic: function (t) {
+ var s = 1.70158;
+ var p = 0;
+ var a = 1;
+ if (t === 0) return 0;
+ if ((t /= 1) == 1) return 1;
+ if (!p) p = 1 * 0.3;
+ if (a < Math.abs(1)) {
+ a = 1;
+ s = p / 4;
+ } else s = p / (2 * Math.PI) * Math.asin(1 / a);
+ return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
+ },
+ easeOutElastic: function (t) {
+ var s = 1.70158;
+ var p = 0;
+ var a = 1;
+ if (t === 0) return 0;
+ if ((t /= 1) == 1) return 1;
+ if (!p) p = 1 * 0.3;
+ if (a < Math.abs(1)) {
+ a = 1;
+ s = p / 4;
+ } else s = p / (2 * Math.PI) * Math.asin(1 / a);
+ return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
+ },
+ easeInOutElastic: function (t) {
+ var s = 1.70158;
+ var p = 0;
+ var a = 1;
+ if (t === 0) return 0;
+ if ((t /= 1 / 2) == 2) return 1;
+ if (!p) p = 1 * (0.3 * 1.5);
+ if (a < Math.abs(1)) {
+ a = 1;
+ s = p / 4;
+ } else s = p / (2 * Math.PI) * Math.asin(1 / a);
+ if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
+ return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
+ },
+ easeInBack: function (t) {
+ var s = 1.70158;
+ return 1 * (t /= 1) * t * ((s + 1) * t - s);
+ },
+ easeOutBack: function (t) {
+ var s = 1.70158;
+ return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
+ },
+ easeInOutBack: function (t) {
+ var s = 1.70158;
+ if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
+ return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
+ },
+ easeInBounce: function (t) {
+ return 1 - easingEffects.easeOutBounce(1 - t);
+ },
+ easeOutBounce: function (t) {
+ if ((t /= 1) < (1 / 2.75)) {
+ return 1 * (7.5625 * t * t);
+ } else if (t < (2 / 2.75)) {
+ return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
+ } else if (t < (2.5 / 2.75)) {
+ return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
+ } else {
+ return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
+ }
+ },
+ easeInOutBounce: function (t) {
+ if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;
+ return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
+ }
+ },
+ //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
+ requestAnimFrame = helpers.requestAnimFrame = (function(){
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })(),
+ cancelAnimFrame = helpers.cancelAnimFrame = (function(){
+ return window.cancelAnimationFrame ||
+ window.webkitCancelAnimationFrame ||
+ window.mozCancelAnimationFrame ||
+ window.oCancelAnimationFrame ||
+ window.msCancelAnimationFrame ||
+ function(callback) {
+ return window.clearTimeout(callback, 1000 / 60);
+ };
+ })(),
+ animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){
+
+ var currentStep = 0,
+ easingFunction = easingEffects[easingString] || easingEffects.linear;
+
+ var animationFrame = function(){
+ currentStep++;
+ var stepDecimal = currentStep/totalSteps;
+ var easeDecimal = easingFunction(stepDecimal);
+
+ callback.call(chartInstance,easeDecimal,stepDecimal, currentStep);
+ onProgress.call(chartInstance,easeDecimal,stepDecimal);
+ if (currentStep < totalSteps){
+ chartInstance.animationFrame = requestAnimFrame(animationFrame);
+ } else{
+ onComplete.apply(chartInstance);
+ }
+ };
+ requestAnimFrame(animationFrame);
+ },
+ //-- DOM methods
+ getRelativePosition = helpers.getRelativePosition = function(evt){
+ var mouseX, mouseY;
+ var e = evt.originalEvent || evt,
+ canvas = evt.currentTarget || evt.srcElement,
+ boundingRect = canvas.getBoundingClientRect();
+
+ if (e.touches){
+ mouseX = e.touches[0].clientX - boundingRect.left;
+ mouseY = e.touches[0].clientY - boundingRect.top;
+
+ }
+ else{
+ mouseX = e.clientX - boundingRect.left;
+ mouseY = e.clientY - boundingRect.top;
+ }
+
+ return {
+ x : mouseX,
+ y : mouseY
+ };
+
+ },
+ addEvent = helpers.addEvent = function(node,eventType,method){
+ if (node.addEventListener){
+ node.addEventListener(eventType,method);
+ } else if (node.attachEvent){
+ node.attachEvent("on"+eventType, method);
+ } else {
+ node["on"+eventType] = method;
+ }
+ },
+ removeEvent = helpers.removeEvent = function(node, eventType, handler){
+ if (node.removeEventListener){
+ node.removeEventListener(eventType, handler, false);
+ } else if (node.detachEvent){
+ node.detachEvent("on"+eventType,handler);
+ } else{
+ node["on" + eventType] = noop;
+ }
+ },
+ bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){
+ // Create the events object if it's not already present
+ if (!chartInstance.events) chartInstance.events = {};
+
+ each(arrayOfEvents,function(eventName){
+ chartInstance.events[eventName] = function(){
+ handler.apply(chartInstance, arguments);
+ };
+ addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);
+ });
+ },
+ unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {
+ each(arrayOfEvents, function(handler,eventName){
+ removeEvent(chartInstance.chart.canvas, eventName, handler);
+ });
+ },
+ getMaximumWidth = helpers.getMaximumWidth = function(domNode){
+ var container = domNode.parentNode;
+ // TODO = check cross browser stuff with this.
+ return container.clientWidth;
+ },
+ getMaximumHeight = helpers.getMaximumHeight = function(domNode){
+ var container = domNode.parentNode;
+ // TODO = check cross browser stuff with this.
+ return container.clientHeight;
+ },
+ getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
+ retinaScale = helpers.retinaScale = function(chart){
+ var ctx = chart.ctx,
+ width = chart.canvas.width,
+ height = chart.canvas.height;
+
+ if (window.devicePixelRatio) {
+ ctx.canvas.style.width = width + "px";
+ ctx.canvas.style.height = height + "px";
+ ctx.canvas.height = height * window.devicePixelRatio;
+ ctx.canvas.width = width * window.devicePixelRatio;
+ ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
+ }
+ },
+ //-- Canvas methods
+ clear = helpers.clear = function(chart){
+ chart.ctx.clearRect(0,0,chart.width,chart.height);
+ },
+ fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){
+ return fontStyle + " " + pixelSize+"px " + fontFamily;
+ },
+ longestText = helpers.longestText = function(ctx,font,arrayOfStrings){
+ ctx.font = font;
+ var longest = 0;
+ each(arrayOfStrings,function(string){
+ var textWidth = ctx.measureText(string).width;
+ longest = (textWidth > longest) ? textWidth : longest;
+ });
+ return longest;
+ },
+ drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){
+ ctx.beginPath();
+ ctx.moveTo(x + radius, y);
+ ctx.lineTo(x + width - radius, y);
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
+ ctx.lineTo(x + width, y + height - radius);
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+ ctx.lineTo(x + radius, y + height);
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
+ ctx.lineTo(x, y + radius);
+ ctx.quadraticCurveTo(x, y, x + radius, y);
+ ctx.closePath();
+ };
+
+
+ //Store a reference to each instance - allowing us to globally resize chart instances on window resize.
+ //Destroy method on the chart will remove the instance of the chart from this reference.
+ Chart.instances = {};
+
+ Chart.Type = function(data,options,chart){
+ this.options = options;
+ this.chart = chart;
+ this.id = uid();
+ //Add the chart instance to the global namespace
+ Chart.instances[this.id] = this;
+
+ // Initialize is always called when a chart type is created
+ // By default it is a no op, but it should be extended
+ if (options.responsive){
+ this.resize();
+ }
+ this.initialize.call(this,data);
+ };
+
+ //Core methods that'll be a part of every chart type
+ extend(Chart.Type.prototype,{
+ initialize : function(){return this;},
+ clear : function(){
+ clear(this.chart);
+ return this;
+ },
+ stop : function(){
+ // Stops any current animation loop occuring
+ cancelAnimFrame(this.animationFrame);
+ return this;
+ },
+ resize : function(callback){
+ this.stop();
+ var canvas = this.chart.canvas,
+ newWidth = getMaximumWidth(this.chart.canvas),
+ newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
+
+ canvas.width = this.chart.width = newWidth;
+ canvas.height = this.chart.height = newHeight;
+
+ retinaScale(this.chart);
+
+ if (typeof callback === "function"){
+ callback.apply(this, Array.prototype.slice.call(arguments, 1));
+ }
+ return this;
+ },
+ reflow : noop,
+ render : function(reflow){
+ if (reflow){
+ this.reflow();
+ }
+ if (this.options.animation && !reflow){
+ helpers.animationLoop(
+ this.draw,
+ this.options.animationSteps,
+ this.options.animationEasing,
+ this.options.onAnimationProgress,
+ this.options.onAnimationComplete,
+ this
+ );
+ }
+ else{
+ this.draw();
+ this.options.onAnimationComplete.call(this);
+ }
+ return this;
+ },
+ generateLegend : function(){
+ return template(this.options.legendTemplate,this);
+ },
+ destroy : function(){
+ this.clear();
+ unbindEvents(this, this.events);
+ var canvas = this.chart.canvas;
+
+ // Reset canvas height/width attributes starts a fresh with the canvas context
+ canvas.width = this.chart.width;
+ canvas.height = this.chart.height;
+
+ // < IE9 doesn't support removeProperty
+ if (canvas.style.removeProperty) {
+ canvas.style.removeProperty('width');
+ canvas.style.removeProperty('height');
+ } else {
+ canvas.style.removeAttribute('width');
+ canvas.style.removeAttribute('height');
+ }
+
+ delete Chart.instances[this.id];
+ },
+ showTooltip : function(ChartElements, forceRedraw){
+ // Only redraw the chart if we've actually changed what we're hovering on.
+ if (typeof this.activeElements === 'undefined') this.activeElements = [];
+
+ var isChanged = (function(Elements){
+ var changed = false;
+
+ if (Elements.length !== this.activeElements.length){
+ changed = true;
+ return changed;
+ }
+
+ each(Elements, function(element, index){
+ if (element !== this.activeElements[index]){
+ changed = true;
+ }
+ }, this);
+ return changed;
+ }).call(this, ChartElements);
+
+ if (!isChanged && !forceRedraw){
+ return;
+ }
+ else{
+ this.activeElements = ChartElements;
+ }
+ this.draw();
+ if(this.options.customTooltips){
+ this.options.customTooltips(false);
+ }
+ if (ChartElements.length > 0){
+ // If we have multiple datasets, show a MultiTooltip for all of the data points at that index
+ if (this.datasets && this.datasets.length > 1) {
+ var dataArray,
+ dataIndex;
+
+ for (var i = this.datasets.length - 1; i >= 0; i--) {
+ dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
+ dataIndex = indexOf(dataArray, ChartElements[0]);
+ if (dataIndex !== -1){
+ break;
+ }
+ }
+ var tooltipLabels = [],
+ tooltipColors = [],
+ medianPosition = (function(index) {
+
+ // Get all the points at that particular index
+ var Elements = [],
+ dataCollection,
+ xPositions = [],
+ yPositions = [],
+ xMax,
+ yMax,
+ xMin,
+ yMin;
+ helpers.each(this.datasets, function(dataset){
+ dataCollection = dataset.points || dataset.bars || dataset.segments;
+ if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
+ Elements.push(dataCollection[dataIndex]);
+ }
+ });
+
+ helpers.each(Elements, function(element) {
+ xPositions.push(element.x);
+ yPositions.push(element.y);
+
+
+ //Include any colour information about the element
+ tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
+ tooltipColors.push({
+ fill: element._saved.fillColor || element.fillColor,
+ stroke: element._saved.strokeColor || element.strokeColor
+ });
+
+ }, this);
+
+ yMin = min(yPositions);
+ yMax = max(yPositions);
+
+ xMin = min(xPositions);
+ xMax = max(xPositions);
+
+ return {
+ x: (xMin > this.chart.width/2) ? xMin : xMax,
+ y: (yMin + yMax)/2
+ };
+ }).call(this, dataIndex);
+
+ new Chart.MultiTooltip({
+ x: medianPosition.x,
+ y: medianPosition.y,
+ xPadding: this.options.tooltipXPadding,
+ yPadding: this.options.tooltipYPadding,
+ xOffset: this.options.tooltipXOffset,
+ fillColor: this.options.tooltipFillColor,
+ textColor: this.options.tooltipFontColor,
+ fontFamily: this.options.tooltipFontFamily,
+ fontStyle: this.options.tooltipFontStyle,
+ fontSize: this.options.tooltipFontSize,
+ titleTextColor: this.options.tooltipTitleFontColor,
+ titleFontFamily: this.options.tooltipTitleFontFamily,
+ titleFontStyle: this.options.tooltipTitleFontStyle,
+ titleFontSize: this.options.tooltipTitleFontSize,
+ cornerRadius: this.options.tooltipCornerRadius,
+ labels: tooltipLabels,
+ legendColors: tooltipColors,
+ legendColorBackground : this.options.multiTooltipKeyBackground,
+ title: ChartElements[0].label,
+ chart: this.chart,
+ ctx: this.chart.ctx,
+ custom: this.options.customTooltips
+ }).draw();
+
+ } else {
+ each(ChartElements, function(Element) {
+ var tooltipPosition = Element.tooltipPosition();
+ new Chart.Tooltip({
+ x: Math.round(tooltipPosition.x),
+ y: Math.round(tooltipPosition.y),
+ xPadding: this.options.tooltipXPadding,
+ yPadding: this.options.tooltipYPadding,
+ fillColor: this.options.tooltipFillColor,
+ textColor: this.options.tooltipFontColor,
+ fontFamily: this.options.tooltipFontFamily,
+ fontStyle: this.options.tooltipFontStyle,
+ fontSize: this.options.tooltipFontSize,
+ caretHeight: this.options.tooltipCaretSize,
+ cornerRadius: this.options.tooltipCornerRadius,
+ text: template(this.options.tooltipTemplate, Element),
+ chart: this.chart,
+ custom: this.options.customTooltips
+ }).draw();
+ }, this);
+ }
+ }
+ return this;
+ },
+ toBase64Image : function(){
+ return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
+ }
+ });
+
+ Chart.Type.extend = function(extensions){
+
+ var parent = this;
+
+ var ChartType = function(){
+ return parent.apply(this,arguments);
+ };
+
+ //Copy the prototype object of the this class
+ ChartType.prototype = clone(parent.prototype);
+ //Now overwrite some of the properties in the base class with the new extensions
+ extend(ChartType.prototype, extensions);
+
+ ChartType.extend = Chart.Type.extend;
+
+ if (extensions.name || parent.prototype.name){
+
+ var chartName = extensions.name || parent.prototype.name;
+ //Assign any potential default values of the new chart type
+
+ //If none are defined, we'll use a clone of the chart type this is being extended from.
+ //I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
+ //doesn't define some defaults of their own.
+
+ var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
+
+ Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults);
+
+ Chart.types[chartName] = ChartType;
+
+ //Register this new chart type in the Chart prototype
+ Chart.prototype[chartName] = function(data,options){
+ var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});
+ return new ChartType(data,config,this);
+ };
+ } else{
+ warn("Name not provided for this chart, so it hasn't been registered");
+ }
+ return parent;
+ };
+
+ Chart.Element = function(configuration){
+ extend(this,configuration);
+ this.initialize.apply(this,arguments);
+ this.save();
+ };
+ extend(Chart.Element.prototype,{
+ initialize : function(){},
+ restore : function(props){
+ if (!props){
+ extend(this,this._saved);
+ } else {
+ each(props,function(key){
+ this[key] = this._saved[key];
+ },this);
+ }
+ return this;
+ },
+ save : function(){
+ this._saved = clone(this);
+ delete this._saved._saved;
+ return this;
+ },
+ update : function(newProps){
+ each(newProps,function(value,key){
+ this._saved[key] = this[key];
+ this[key] = value;
+ },this);
+ return this;
+ },
+ transition : function(props,ease){
+ each(props,function(value,key){
+ this[key] = ((value - this._saved[key]) * ease) + this._saved[key];
+ },this);
+ return this;
+ },
+ tooltipPosition : function(){
+ return {
+ x : this.x,
+ y : this.y
+ };
+ },
+ hasValue: function(){
+ return isNumber(this.value);
+ }
+ });
+
+ Chart.Element.extend = inherits;
+
+
+ Chart.Point = Chart.Element.extend({
+ display: true,
+ inRange: function(chartX,chartY){
+ var hitDetectionRange = this.hitDetectionRadius + this.radius;
+ return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));
+ },
+ draw : function(){
+ if (this.display){
+ var ctx = this.ctx;
+ ctx.beginPath();
+
+ ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
+ ctx.closePath();
+
+ ctx.strokeStyle = this.strokeColor;
+ ctx.lineWidth = this.strokeWidth;
+
+ ctx.fillStyle = this.fillColor;
+
+ ctx.fill();
+ ctx.stroke();
+ }
+
+
+ //Quick debug for bezier curve splining
+ //Highlights control points and the line between them.
+ //Handy for dev - stripped in the min version.
+
+ // ctx.save();
+ // ctx.fillStyle = "black";
+ // ctx.strokeStyle = "black"
+ // ctx.beginPath();
+ // ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);
+ // ctx.fill();
+
+ // ctx.beginPath();
+ // ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);
+ // ctx.fill();
+
+ // ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);
+ // ctx.lineTo(this.x, this.y);
+ // ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);
+ // ctx.stroke();
+
+ // ctx.restore();
+
+
+
+ }
+ });
+
+ Chart.Arc = Chart.Element.extend({
+ inRange : function(chartX,chartY){
+
+ var pointRelativePosition = helpers.getAngleFromPoint(this, {
+ x: chartX,
+ y: chartY
+ });
+
+ //Check if within the range of the open/close angle
+ var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
+ withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);
+
+ return (betweenAngles && withinRadius);
+ //Ensure within the outside of the arc centre, but inside arc outer
+ },
+ tooltipPosition : function(){
+ var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
+ rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
+ return {
+ x : this.x + (Math.cos(centreAngle) * rangeFromCentre),
+ y : this.y + (Math.sin(centreAngle) * rangeFromCentre)
+ };
+ },
+ draw : function(animationPercent){
+
+ var easingDecimal = animationPercent || 1;
+
+ var ctx = this.ctx;
+
+ ctx.beginPath();
+
+ ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);
+
+ ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);
+
+ ctx.closePath();
+ ctx.strokeStyle = this.strokeColor;
+ ctx.lineWidth = this.strokeWidth;
+
+ ctx.fillStyle = this.fillColor;
+
+ ctx.fill();
+ ctx.lineJoin = 'bevel';
+
+ if (this.showStroke){
+ ctx.stroke();
+ }
+ }
+ });
+
+ Chart.Rectangle = Chart.Element.extend({
+ draw : function(){
+ var ctx = this.ctx,
+ halfWidth = this.width/2,
+ leftX = this.x - halfWidth,
+ rightX = this.x + halfWidth,
+ top = this.base - (this.base - this.y),
+ halfStroke = this.strokeWidth / 2;
+
+ // Canvas doesn't allow us to stroke inside the width so we can
+ // adjust the sizes to fit if we're setting a stroke on the line
+ if (this.showStroke){
+ leftX += halfStroke;
+ rightX -= halfStroke;
+ top += halfStroke;
+ }
+
+ ctx.beginPath();
+
+ ctx.fillStyle = this.fillColor;
+ ctx.strokeStyle = this.strokeColor;
+ ctx.lineWidth = this.strokeWidth;
+
+ // It'd be nice to keep this class totally generic to any rectangle
+ // and simply specify which border to miss out.
+ ctx.moveTo(leftX, this.base);
+ ctx.lineTo(leftX, top);
+ ctx.lineTo(rightX, top);
+ ctx.lineTo(rightX, this.base);
+ ctx.fill();
+ if (this.showStroke){
+ ctx.stroke();
+ }
+ },
+ height : function(){
+ return this.base - this.y;
+ },
+ inRange : function(chartX,chartY){
+ return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);
+ }
+ });
+
+ Chart.Tooltip = Chart.Element.extend({
+ draw : function(){
+
+ var ctx = this.chart.ctx;
+
+ ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
+
+ this.xAlign = "center";
+ this.yAlign = "above";
+
+ //Distance between the actual element.y position and the start of the tooltip caret
+ var caretPadding = this.caretPadding = 2;
+
+ var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
+ tooltipRectHeight = this.fontSize + 2*this.yPadding,
+ tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;
+
+ if (this.x + tooltipWidth/2 >this.chart.width){
+ this.xAlign = "left";
+ } else if (this.x - tooltipWidth/2 < 0){
+ this.xAlign = "right";
+ }
+
+ if (this.y - tooltipHeight < 0){
+ this.yAlign = "below";
+ }
+
+
+ var tooltipX = this.x - tooltipWidth/2,
+ tooltipY = this.y - tooltipHeight;
+
+ ctx.fillStyle = this.fillColor;
+
+ // Custom Tooltips
+ if(this.custom){
+ this.custom(this);
+ }
+ else{
+ switch(this.yAlign)
+ {
+ case "above":
+ //Draw a caret above the x/y
+ ctx.beginPath();
+ ctx.moveTo(this.x,this.y - caretPadding);
+ ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
+ ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
+ ctx.closePath();
+ ctx.fill();
+ break;
+ case "below":
+ tooltipY = this.y + caretPadding + this.caretHeight;
+ //Draw a caret below the x/y
+ ctx.beginPath();
+ ctx.moveTo(this.x, this.y + caretPadding);
+ ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
+ ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
+ ctx.closePath();
+ ctx.fill();
+ break;
+ }
+
+ switch(this.xAlign)
+ {
+ case "left":
+ tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
+ break;
+ case "right":
+ tooltipX = this.x - (this.cornerRadius + this.caretHeight);
+ break;
+ }
+
+ drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
+
+ ctx.fill();
+
+ ctx.fillStyle = this.textColor;
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
+ }
+ }
+ });
+
+ Chart.MultiTooltip = Chart.Element.extend({
+ initialize : function(){
+ this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
+
+ this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);
+
+ this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;
+
+ this.ctx.font = this.titleFont;
+
+ var titleWidth = this.ctx.measureText(this.title).width,
+ //Label has a legend square as well so account for this.
+ labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,
+ longestTextWidth = max([labelWidth,titleWidth]);
+
+ this.width = longestTextWidth + (this.xPadding*2);
+
+
+ var halfHeight = this.height/2;
+
+ //Check to ensure the height will fit on the canvas
+ if (this.y - halfHeight < 0 ){
+ this.y = halfHeight;
+ } else if (this.y + halfHeight > this.chart.height){
+ this.y = this.chart.height - halfHeight;
+ }
+
+ //Decide whether to align left or right based on position on canvas
+ if (this.x > this.chart.width/2){
+ this.x -= this.xOffset + this.width;
+ } else {
+ this.x += this.xOffset;
+ }
+
+
+ },
+ getLineHeight : function(index){
+ var baseLineHeight = this.y - (this.height/2) + this.yPadding,
+ afterTitleIndex = index-1;
+
+ //If the index is zero, we're getting the title
+ if (index === 0){
+ return baseLineHeight + this.titleFontSize/2;
+ } else{
+ return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;
+ }
+
+ },
+ draw : function(){
+ // Custom Tooltips
+ if(this.custom){
+ this.custom(this);
+ }
+ else{
+ drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
+ var ctx = this.ctx;
+ ctx.fillStyle = this.fillColor;
+ ctx.fill();
+ ctx.closePath();
+
+ ctx.textAlign = "left";
+ ctx.textBaseline = "middle";
+ ctx.fillStyle = this.titleTextColor;
+ ctx.font = this.titleFont;
+
+ ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
+
+ ctx.font = this.font;
+ helpers.each(this.labels,function(label,index){
+ ctx.fillStyle = this.textColor;
+ ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
+
+ //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
+ //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+ //Instead we'll make a white filled block to put the legendColour palette over.
+
+ ctx.fillStyle = this.legendColorBackground;
+ ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+
+ ctx.fillStyle = this.legendColors[index].fill;
+ ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+
+
+ },this);
+ }
+ }
+ });
+
+ Chart.Scale = Chart.Element.extend({
+ initialize : function(){
+ this.fit();
+ },
+ buildYLabels : function(){
+ this.yLabels = [];
+
+ var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
+
+ for (var i=0; i<=this.steps; i++){
+ this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
+ }
+ this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;
+ },
+ addXLabel : function(label){
+ this.xLabels.push(label);
+ this.valuesCount++;
+ this.fit();
+ },
+ removeXLabel : function(){
+ this.xLabels.shift();
+ this.valuesCount--;
+ this.fit();
+ },
+ // Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use
+ fit: function(){
+ // First we need the width of the yLabels, assuming the xLabels aren't rotated
+
+ // To do that we need the base line at the top and base of the chart, assuming there is no x label rotation
+ this.startPoint = (this.display) ? this.fontSize : 0;
+ this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels
+
+ // Apply padding settings to the start and end point.
+ this.startPoint += this.padding;
+ this.endPoint -= this.padding;
+
+ // Cache the starting height, so can determine if we need to recalculate the scale yAxis
+ var cachedHeight = this.endPoint - this.startPoint,
+ cachedYLabelWidth;
+
+ // Build the current yLabels so we have an idea of what size they'll be to start
+ /*
+ * This sets what is returned from calculateScaleRange as static properties of this class:
+ *
+ this.steps;
+ this.stepValue;
+ this.min;
+ this.max;
+ *
+ */
+ this.calculateYRange(cachedHeight);
+
+ // With these properties set we can now build the array of yLabels
+ // and also the width of the largest yLabel
+ this.buildYLabels();
+
+ this.calculateXLabelRotation();
+
+ while((cachedHeight > this.endPoint - this.startPoint)){
+ cachedHeight = this.endPoint - this.startPoint;
+ cachedYLabelWidth = this.yLabelWidth;
+
+ this.calculateYRange(cachedHeight);
+ this.buildYLabels();
+
+ // Only go through the xLabel loop again if the yLabel width has changed
+ if (cachedYLabelWidth < this.yLabelWidth){
+ this.calculateXLabelRotation();
+ }
+ }
+
+ },
+ calculateXLabelRotation : function(){
+ //Get the width of each grid by calculating the difference
+ //between x offsets between 0 and 1.
+
+ this.ctx.font = this.font;
+
+ var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
+ lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
+ firstRotated,
+ lastRotated;
+
+
+ this.xScalePaddingRight = lastWidth/2 + 3;
+ this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;
+
+ this.xLabelRotation = 0;
+ if (this.display){
+ var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),
+ cosRotation,
+ firstRotatedWidth;
+ this.xLabelWidth = originalLabelWidth;
+ //Allow 3 pixels x2 padding either side for label readability
+ var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
+
+ //Max label rotate should be 90 - also act as a loop counter
+ while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){
+ cosRotation = Math.cos(toRadians(this.xLabelRotation));
+
+ firstRotated = cosRotation * firstWidth;
+ lastRotated = cosRotation * lastWidth;
+
+ // We're right aligning the text now.
+ if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){
+ this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
+ }
+ this.xScalePaddingRight = this.fontSize/2;
+
+
+ this.xLabelRotation++;
+ this.xLabelWidth = cosRotation * originalLabelWidth;
+
+ }
+ if (this.xLabelRotation > 0){
+ this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;
+ }
+ }
+ else{
+ this.xLabelWidth = 0;
+ this.xScalePaddingRight = this.padding;
+ this.xScalePaddingLeft = this.padding;
+ }
+
+ },
+ // Needs to be overidden in each Chart type
+ // Otherwise we need to pass all the data into the scale class
+ calculateYRange: noop,
+ drawingArea: function(){
+ return this.startPoint - this.endPoint;
+ },
+ calculateY : function(value){
+ var scalingFactor = this.drawingArea() / (this.min - this.max);
+ return this.endPoint - (scalingFactor * (value - this.min));
+ },
+ calculateX : function(index){
+ var isRotated = (this.xLabelRotation > 0),
+ // innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,
+ innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
+ valueWidth = innerWidth/Math.max((this.valuesCount - ((this.offsetGridLines) ? 0 : 1)), 1),
+ valueOffset = (valueWidth * index) + this.xScalePaddingLeft;
+
+ if (this.offsetGridLines){
+ valueOffset += (valueWidth/2);
+ }
+
+ return Math.round(valueOffset);
+ },
+ update : function(newProps){
+ helpers.extend(this, newProps);
+ this.fit();
+ },
+ draw : function(){
+ var ctx = this.ctx,
+ yLabelGap = (this.endPoint - this.startPoint) / this.steps,
+ xStart = Math.round(this.xScalePaddingLeft);
+ if (this.display){
+ ctx.fillStyle = this.textColor;
+ ctx.font = this.font;
+ each(this.yLabels,function(labelString,index){
+ var yLabelCenter = this.endPoint - (yLabelGap * index),
+ linePositionY = Math.round(yLabelCenter),
+ drawHorizontalLine = this.showHorizontalLines;
+
+ ctx.textAlign = "right";
+ ctx.textBaseline = "middle";
+ if (this.showLabels){
+ ctx.fillText(labelString,xStart - 10,yLabelCenter);
+ }
+
+ // This is X axis, so draw it
+ if (index === 0 && !drawHorizontalLine){
+ drawHorizontalLine = true;
+ }
+
+ if (drawHorizontalLine){
+ ctx.beginPath();
+ }
+
+ if (index > 0){
+ // This is a grid line in the centre, so drop that
+ ctx.lineWidth = this.gridLineWidth;
+ ctx.strokeStyle = this.gridLineColor;
+ } else {
+ // This is the first line on the scale
+ ctx.lineWidth = this.lineWidth;
+ ctx.strokeStyle = this.lineColor;
+ }
+
+ linePositionY += helpers.aliasPixel(ctx.lineWidth);
+
+ if(drawHorizontalLine){
+ ctx.moveTo(xStart, linePositionY);
+ ctx.lineTo(this.width, linePositionY);
+ ctx.stroke();
+ ctx.closePath();
+ }
+
+ ctx.lineWidth = this.lineWidth;
+ ctx.strokeStyle = this.lineColor;
+ ctx.beginPath();
+ ctx.moveTo(xStart - 5, linePositionY);
+ ctx.lineTo(xStart, linePositionY);
+ ctx.stroke();
+ ctx.closePath();
+
+ },this);
+
+ each(this.xLabels,function(label,index){
+ var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
+ // Check to see if line/bar here and decide where to place the line
+ linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
+ isRotated = (this.xLabelRotation > 0),
+ drawVerticalLine = this.showVerticalLines;
+
+ // This is Y axis, so draw it
+ if (index === 0 && !drawVerticalLine){
+ drawVerticalLine = true;
+ }
+
+ if (drawVerticalLine){
+ ctx.beginPath();
+ }
+
+ if (index > 0){
+ // This is a grid line in the centre, so drop that
+ ctx.lineWidth = this.gridLineWidth;
+ ctx.strokeStyle = this.gridLineColor;
+ } else {
+ // This is the first line on the scale
+ ctx.lineWidth = this.lineWidth;
+ ctx.strokeStyle = this.lineColor;
+ }
+
+ if (drawVerticalLine){
+ ctx.moveTo(linePos,this.endPoint);
+ ctx.lineTo(linePos,this.startPoint - 3);
+ ctx.stroke();
+ ctx.closePath();
+ }
+
+
+ ctx.lineWidth = this.lineWidth;
+ ctx.strokeStyle = this.lineColor;
+
+
+ // Small lines at the bottom of the base grid line
+ ctx.beginPath();
+ ctx.moveTo(linePos,this.endPoint);
+ ctx.lineTo(linePos,this.endPoint + 5);
+ ctx.stroke();
+ ctx.closePath();
+
+ ctx.save();
+ ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);
+ ctx.rotate(toRadians(this.xLabelRotation)*-1);
+ ctx.font = this.font;
+ ctx.textAlign = (isRotated) ? "right" : "center";
+ ctx.textBaseline = (isRotated) ? "middle" : "top";
+ ctx.fillText(label, 0, 0);
+ ctx.restore();
+ },this);
+
+ }
+ }
+
+ });
+
+ Chart.RadialScale = Chart.Element.extend({
+ initialize: function(){
+ this.size = min([this.height, this.width]);
+ this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
+ },
+ calculateCenterOffset: function(value){
+ // Take into account half font size + the yPadding of the top value
+ var scalingFactor = this.drawingArea / (this.max - this.min);
+
+ return (value - this.min) * scalingFactor;
+ },
+ update : function(){
+ if (!this.lineArc){
+ this.setScaleSize();
+ } else {
+ this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
+ }
+ this.buildYLabels();
+ },
+ buildYLabels: function(){
+ this.yLabels = [];
+
+ var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
+
+ for (var i=0; i<=this.steps; i++){
+ this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
+ }
+ },
+ getCircumference : function(){
+ return ((Math.PI*2) / this.valuesCount);
+ },
+ setScaleSize: function(){
+ /*
+ * Right, this is really confusing and there is a lot of maths going on here
+ * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
+ *
+ * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
+ *
+ * Solution:
+ *
+ * We assume the radius of the polygon is half the size of the canvas at first
+ * at each index we check if the text overlaps.
+ *
+ * Where it does, we store that angle and that index.
+ *
+ * After finding the largest index and angle we calculate how much we need to remove
+ * from the shape radius to move the point inwards by that x.
+ *
+ * We average the left and right distances to get the maximum shape radius that can fit in the box
+ * along with labels.
+ *
+ * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
+ * on each side, removing that from the size, halving it and adding the left x protrusion width.
+ *
+ * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
+ * and position it in the most space efficient manner
+ *
+ * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
+ */
+
+
+ // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
+ // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
+ var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),
+ pointPosition,
+ i,
+ textWidth,
+ halfTextWidth,
+ furthestRight = this.width,
+ furthestRightIndex,
+ furthestRightAngle,
+ furthestLeft = 0,
+ furthestLeftIndex,
+ furthestLeftAngle,
+ xProtrusionLeft,
+ xProtrusionRight,
+ radiusReductionRight,
+ radiusReductionLeft,
+ maxWidthRadius;
+ this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
+ for (i=0;i<this.valuesCount;i++){
+ // 5px to space the text slightly out - similar to what we do in the draw function.
+ pointPosition = this.getPointPosition(i, largestPossibleRadius);
+ textWidth = this.ctx.measureText(template(this.templateString, { value: this.labels[i] })).width + 5;
+ if (i === 0 || i === this.valuesCount/2){
+ // If we're at index zero, or exactly the middle, we're at exactly the top/bottom
+ // of the radar chart, so text will be aligned centrally, so we'll half it and compare
+ // w/left and right text sizes
+ halfTextWidth = textWidth/2;
+ if (pointPosition.x + halfTextWidth > furthestRight) {
+ furthestRight = pointPosition.x + halfTextWidth;
+ furthestRightIndex = i;
+ }
+ if (pointPosition.x - halfTextWidth < furthestLeft) {
+ furthestLeft = pointPosition.x - halfTextWidth;
+ furthestLeftIndex = i;
+ }
+ }
+ else if (i < this.valuesCount/2) {
+ // Less than half the values means we'll left align the text
+ if (pointPosition.x + textWidth > furthestRight) {
+ furthestRight = pointPosition.x + textWidth;
+ furthestRightIndex = i;
+ }
+ }
+ else if (i > this.valuesCount/2){
+ // More than half the values means we'll right align the text
+ if (pointPosition.x - textWidth < furthestLeft) {
+ furthestLeft = pointPosition.x - textWidth;
+ furthestLeftIndex = i;
+ }
+ }
+ }
+
+ xProtrusionLeft = furthestLeft;
+
+ xProtrusionRight = Math.ceil(furthestRight - this.width);
+
+ furthestRightAngle = this.getIndexAngle(furthestRightIndex);
+
+ furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
+
+ radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);
+
+ radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);
+
+ // Ensure we actually need to reduce the size of the chart
+ radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
+ radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
+
+ this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;
+
+ //this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])
+ this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
+
+ },
+ setCenterPoint: function(leftMovement, rightMovement){
+
+ var maxRight = this.width - rightMovement - this.drawingArea,
+ maxLeft = leftMovement + this.drawingArea;
+
+ this.xCenter = (maxLeft + maxRight)/2;
+ // Always vertically in the centre as the text height doesn't change
+ this.yCenter = (this.height/2);
+ },
+
+ getIndexAngle : function(index){
+ var angleMultiplier = (Math.PI * 2) / this.valuesCount;
+ // Start from the top instead of right, so remove a quarter of the circle
+
+ return index * angleMultiplier - (Math.PI/2);
+ },
+ getPointPosition : function(index, distanceFromCenter){
+ var thisAngle = this.getIndexAngle(index);
+ return {
+ x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,
+ y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter
+ };
+ },
+ draw: function(){
+ if (this.display){
+ var ctx = this.ctx;
+ each(this.yLabels, function(label, index){
+ // Don't draw a centre value
+ if (index > 0){
+ var yCenterOffset = index * (this.drawingArea/this.steps),
+ yHeight = this.yCenter - yCenterOffset,
+ pointPosition;
+
+ // Draw circular lines around the scale
+ if (this.lineWidth > 0){
+ ctx.strokeStyle = this.lineColor;
+ ctx.lineWidth = this.lineWidth;
+
+ if(this.lineArc){
+ ctx.beginPath();
+ ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);
+ ctx.closePath();
+ ctx.stroke();
+ } else{
+ ctx.beginPath();
+ for (var i=0;i<this.valuesCount;i++)
+ {
+ pointPosition = this.getPointPosition(i, this.calculateCenterOffset(this.min + (index * this.stepValue)));
+ if (i === 0){
+ ctx.moveTo(pointPosition.x, pointPosition.y);
+ } else {
+ ctx.lineTo(pointPosition.x, pointPosition.y);
+ }
+ }
+ ctx.closePath();
+ ctx.stroke();
+ }
+ }
+ if(this.showLabels){
+ ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
+ if (this.showLabelBackdrop){
+ var labelWidth = ctx.measureText(label).width;
+ ctx.fillStyle = this.backdropColor;
+ ctx.fillRect(
+ this.xCenter - labelWidth/2 - this.backdropPaddingX,
+ yHeight - this.fontSize/2 - this.backdropPaddingY,
+ labelWidth + this.backdropPaddingX*2,
+ this.fontSize + this.backdropPaddingY*2
+ );
+ }
+ ctx.textAlign = 'center';
+ ctx.textBaseline = "middle";
+ ctx.fillStyle = this.fontColor;
+ ctx.fillText(label, this.xCenter, yHeight);
+ }
+ }
+ }, this);
+
+ if (!this.lineArc){
+ ctx.lineWidth = this.angleLineWidth;
+ ctx.strokeStyle = this.angleLineColor;
+ for (var i = this.valuesCount - 1; i >= 0; i--) {
+ if (this.angleLineWidth > 0){
+ var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));
+ ctx.beginPath();
+ ctx.moveTo(this.xCenter, this.yCenter);
+ ctx.lineTo(outerPosition.x, outerPosition.y);
+ ctx.stroke();
+ ctx.closePath();
+ }
+ // Extra 3px out for some label spacing
+ var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);
+ ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
+ ctx.fillStyle = this.pointLabelFontColor;
+
+ var labelsCount = this.labels.length,
+ halfLabelsCount = this.labels.length/2,
+ quarterLabelsCount = halfLabelsCount/2,
+ upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
+ exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
+ if (i === 0){
+ ctx.textAlign = 'center';
+ } else if(i === halfLabelsCount){
+ ctx.textAlign = 'center';
+ } else if (i < halfLabelsCount){
+ ctx.textAlign = 'left';
+ } else {
+ ctx.textAlign = 'right';
+ }
+
+ // Set the correct text baseline based on outer positioning
+ if (exactQuarter){
+ ctx.textBaseline = 'middle';
+ } else if (upperHalf){
+ ctx.textBaseline = 'bottom';
+ } else {
+ ctx.textBaseline = 'top';
+ }
+
+ ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);
+ }
+ }
+ }
+ }
+ });
+
+ // Attach global event to resize each chart instance when the browser resizes
+ helpers.addEvent(window, "resize", (function(){
+ // Basic debounce of resize function so it doesn't hurt performance when resizing browser.
+ var timeout;
+ return function(){
+ clearTimeout(timeout);
+ timeout = setTimeout(function(){
+ each(Chart.instances,function(instance){
+ // If the responsive flag is set in the chart instance config
+ // Cascade the resize event down to the chart.
+ if (instance.options.responsive){
+ instance.resize(instance.render, true);
+ }
+ });
+ }, 50);
+ };
+ })());
+
+
+ if (amd) {
+ define(function(){
+ return Chart;
+ });
+ } else if (typeof module === 'object' && module.exports) {
+ module.exports = Chart;
+ }
+
+ root.Chart = Chart;
+
+ Chart.noConflict = function(){
+ root.Chart = previous;
+ return Chart;
+ };
+
+}).call(this);
+
+(function(){
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ helpers = Chart.helpers;
+
+
+ var defaultConfig = {
+ //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
+ scaleBeginAtZero : true,
+
+ //Boolean - Whether grid lines are shown across the chart
+ scaleShowGridLines : true,
+
+ //String - Colour of the grid lines
+ scaleGridLineColor : "rgba(0,0,0,.05)",
+
+ //Number - Width of the grid lines
+ scaleGridLineWidth : 1,
+
+ //Boolean - Whether to show horizontal lines (except X axis)
+ scaleShowHorizontalLines: true,
+
+ //Boolean - Whether to show vertical lines (except Y axis)
+ scaleShowVerticalLines: true,
+
+ //Boolean - If there is a stroke on each bar
+ barShowStroke : true,
+
+ //Number - Pixel width of the bar stroke
+ barStrokeWidth : 2,
+
+ //Number - Spacing between each of the X value sets
+ barValueSpacing : 5,
+
+ //Number - Spacing between data sets within X values
+ barDatasetSpacing : 1,
+
+ //String - A legend template
+ legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
+
+ };
+
+
+ Chart.Type.extend({
+ name: "Bar",
+ defaults : defaultConfig,
+ initialize: function(data){
+
+ //Expose options as a scope variable here so we can access it in the ScaleClass
+ var options = this.options;
+
+ this.ScaleClass = Chart.Scale.extend({
+ offsetGridLines : true,
+ calculateBarX : function(datasetCount, datasetIndex, barIndex){
+ //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
+ var xWidth = this.calculateBaseWidth(),
+ xAbsolute = this.calculateX(barIndex) - (xWidth/2),
+ barWidth = this.calculateBarWidth(datasetCount);
+
+ return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
+ },
+ calculateBaseWidth : function(){
+ return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
+ },
+ calculateBarWidth : function(datasetCount){
+ //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
+ var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
+
+ return (baseWidth / datasetCount);
+ }
+ });
+
+ this.datasets = [];
+
+ //Set up tooltip events on the chart
+ if (this.options.showTooltips){
+ helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
+ var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
+
+ this.eachBars(function(bar){
+ bar.restore(['fillColor', 'strokeColor']);
+ });
+ helpers.each(activeBars, function(activeBar){
+ activeBar.fillColor = activeBar.highlightFill;
+ activeBar.strokeColor = activeBar.highlightStroke;
+ });
+ this.showTooltip(activeBars);
+ });
+ }
+
+ //Declare the extension of the default point, to cater for the options passed in to the constructor
+ this.BarClass = Chart.Rectangle.extend({
+ strokeWidth : this.options.barStrokeWidth,
+ showStroke : this.options.barShowStroke,
+ ctx : this.chart.ctx
+ });
+
+ //Iterate through each of the datasets, and build this into a property of the chart
+ helpers.each(data.datasets,function(dataset,datasetIndex){
+
+ var datasetObject = {
+ label : dataset.label || null,
+ fillColor : dataset.fillColor,
+ strokeColor : dataset.strokeColor,
+ bars : []
+ };
+
+ this.datasets.push(datasetObject);
+
+ helpers.each(dataset.data,function(dataPoint,index){
+ //Add a new point for each piece of data, passing any required data to draw.
+ datasetObject.bars.push(new this.BarClass({
+ value : dataPoint,
+ label : data.labels[index],
+ datasetLabel: dataset.label,
+ strokeColor : dataset.strokeColor,
+ fillColor : dataset.fillColor,
+ highlightFill : dataset.highlightFill || dataset.fillColor,
+ highlightStroke : dataset.highlightStroke || dataset.strokeColor
+ }));
+ },this);
+
+ },this);
+
+ this.buildScale(data.labels);
+
+ this.BarClass.prototype.base = this.scale.endPoint;
+
+ this.eachBars(function(bar, index, datasetIndex){
+ helpers.extend(bar, {
+ width : this.scale.calculateBarWidth(this.datasets.length),
+ x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
+ y: this.scale.endPoint
+ });
+ bar.save();
+ }, this);
+
+ this.render();
+ },
+ update : function(){
+ this.scale.update();
+ // Reset any highlight colours before updating.
+ helpers.each(this.activeElements, function(activeElement){
+ activeElement.restore(['fillColor', 'strokeColor']);
+ });
+
+ this.eachBars(function(bar){
+ bar.save();
+ });
+ this.render();
+ },
+ eachBars : function(callback){
+ helpers.each(this.datasets,function(dataset, datasetIndex){
+ helpers.each(dataset.bars, callback, this, datasetIndex);
+ },this);
+ },
+ getBarsAtEvent : function(e){
+ var barsArray = [],
+ eventPosition = helpers.getRelativePosition(e),
+ datasetIterator = function(dataset){
+ barsArray.push(dataset.bars[barIndex]);
+ },
+ barIndex;
+
+ for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
+ for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
+ if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
+ helpers.each(this.datasets, datasetIterator);
+ return barsArray;
+ }
+ }
+ }
+
+ return barsArray;
+ },
+ buildScale : function(labels){
+ var self = this;
+
+ var dataTotal = function(){
+ var values = [];
+ self.eachBars(function(bar){
+ values.push(bar.value);
+ });
+ return values;
+ };
+
+ var scaleOptions = {
+ templateString : this.options.scaleLabel,
+ height : this.chart.height,
+ width : this.chart.width,
+ ctx : this.chart.ctx,
+ textColor : this.options.scaleFontColor,
+ fontSize : this.options.scaleFontSize,
+ fontStyle : this.options.scaleFontStyle,
+ fontFamily : this.options.scaleFontFamily,
+ valuesCount : labels.length,
+ beginAtZero : this.options.scaleBeginAtZero,
+ integersOnly : this.options.scaleIntegersOnly,
+ calculateYRange: function(currentHeight){
+ var updatedRanges = helpers.calculateScaleRange(
+ dataTotal(),
+ currentHeight,
+ this.fontSize,
+ this.beginAtZero,
+ this.integersOnly
+ );
+ helpers.extend(this, updatedRanges);
+ },
+ xLabels : labels,
+ font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
+ lineWidth : this.options.scaleLineWidth,
+ lineColor : this.options.scaleLineColor,
+ showHorizontalLines : this.options.scaleShowHorizontalLines,
+ showVerticalLines : this.options.scaleShowVerticalLines,
+ gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
+ gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
+ padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
+ showLabels : this.options.scaleShowLabels,
+ display : this.options.showScale
+ };
+
+ if (this.options.scaleOverride){
+ helpers.extend(scaleOptions, {
+ calculateYRange: helpers.noop,
+ steps: this.options.scaleSteps,
+ stepValue: this.options.scaleStepWidth,
+ min: this.options.scaleStartValue,
+ max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
+ });
+ }
+
+ this.scale = new this.ScaleClass(scaleOptions);
+ },
+ addData : function(valuesArray,label){
+ //Map the values array for each of the datasets
+ helpers.each(valuesArray,function(value,datasetIndex){
+ //Add a new point for each piece of data, passing any required data to draw.
+ this.datasets[datasetIndex].bars.push(new this.BarClass({
+ value : value,
+ label : label,
+ x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
+ y: this.scale.endPoint,
+ width : this.scale.calculateBarWidth(this.datasets.length),
+ base : this.scale.endPoint,
+ strokeColor : this.datasets[datasetIndex].strokeColor,
+ fillColor : this.datasets[datasetIndex].fillColor
+ }));
+ },this);
+
+ this.scale.addXLabel(label);
+ //Then re-render the chart.
+ this.update();
+ },
+ removeData : function(){
+ this.scale.removeXLabel();
+ //Then re-render the chart.
+ helpers.each(this.datasets,function(dataset){
+ dataset.bars.shift();
+ },this);
+ this.update();
+ },
+ reflow : function(){
+ helpers.extend(this.BarClass.prototype,{
+ y: this.scale.endPoint,
+ base : this.scale.endPoint
+ });
+ var newScaleProps = helpers.extend({
+ height : this.chart.height,
+ width : this.chart.width
+ });
+ this.scale.update(newScaleProps);
+ },
+ draw : function(ease){
+ var easingDecimal = ease || 1;
+ this.clear();
+
+ var ctx = this.chart.ctx;
+
+ this.scale.draw(easingDecimal);
+
+ //Draw all the bars for each dataset
+ helpers.each(this.datasets,function(dataset,datasetIndex){
+ helpers.each(dataset.bars,function(bar,index){
+ if (bar.hasValue()){
+ bar.base = this.scale.endPoint;
+ //Transition then draw
+ bar.transition({
+ x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
+ y : this.scale.calculateY(bar.value),
+ width : this.scale.calculateBarWidth(this.datasets.length)
+ }, easingDecimal).draw();
+ }
+ },this);
+
+ },this);
+ }
+ });
+
+
+}).call(this);
+
+(function(){
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ //Cache a local reference to Chart.helpers
+ helpers = Chart.helpers;
+
+ var defaultConfig = {
+ //Boolean - Whether we should show a stroke on each segment
+ segmentShowStroke : true,
+
+ //String - The colour of each segment stroke
+ segmentStrokeColor : "#fff",
+
+ //Number - The width of each segment stroke
+ segmentStrokeWidth : 2,
+
+ //The percentage of the chart that we cut out of the middle.
+ percentageInnerCutout : 50,
+
+ //Number - Amount of animation steps
+ animationSteps : 100,
+
+ //String - Animation easing effect
+ animationEasing : "easeOutBounce",
+
+ //Boolean - Whether we animate the rotation of the Doughnut
+ animateRotate : true,
+
+ //Boolean - Whether we animate scaling the Doughnut from the centre
+ animateScale : false,
+
+ //String - A legend template
+ legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
+
+ };
+
+
+ Chart.Type.extend({
+ //Passing in a name registers this chart in the Chart namespace
+ name: "Doughnut",
+ //Providing a defaults will also register the deafults in the chart namespace
+ defaults : defaultConfig,
+ //Initialize is fired when the chart is initialized - Data is passed in as a parameter
+ //Config is automatically merged by the core of Chart.js, and is available at this.options
+ initialize: function(data){
+
+ //Declare segments as a static property to prevent inheriting across the Chart type prototype
+ this.segments = [];
+ this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
+
+ this.SegmentArc = Chart.Arc.extend({
+ ctx : this.chart.ctx,
+ x : this.chart.width/2,
+ y : this.chart.height/2
+ });
+
+ //Set up tooltip events on the chart
+ if (this.options.showTooltips){
+ helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
+ var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
+
+ helpers.each(this.segments,function(segment){
+ segment.restore(["fillColor"]);
+ });
+ helpers.each(activeSegments,function(activeSegment){
+ activeSegment.fillColor = activeSegment.highlightColor;
+ });
+ this.showTooltip(activeSegments);
+ });
+ }
+ this.calculateTotal(data);
+
+ helpers.each(data,function(datapoint, index){
+ this.addData(datapoint, index, true);
+ },this);
+
+ this.render();
+ },
+ getSegmentsAtEvent : function(e){
+ var segmentsArray = [];
+
+ var location = helpers.getRelativePosition(e);
+
+ helpers.each(this.segments,function(segment){
+ if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
+ },this);
+ return segmentsArray;
+ },
+ addData : function(segment, atIndex, silent){
+ var index = atIndex || this.segments.length;
+ this.segments.splice(index, 0, new this.SegmentArc({
+ value : segment.value,
+ outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
+ innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
+ fillColor : segment.color,
+ highlightColor : segment.highlight || segment.color,
+ showStroke : this.options.segmentShowStroke,
+ strokeWidth : this.options.segmentStrokeWidth,
+ strokeColor : this.options.segmentStrokeColor,
+ startAngle : Math.PI * 1.5,
+ circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
+ label : segment.label
+ }));
+ if (!silent){
+ this.reflow();
+ this.update();
+ }
+ },
+ calculateCircumference : function(value){
+ return (Math.PI*2)*(Math.abs(value) / this.total);
+ },
+ calculateTotal : function(data){
+ this.total = 0;
+ helpers.each(data,function(segment){
+ this.total += Math.abs(segment.value);
+ },this);
+ },
+ update : function(){
+ this.calculateTotal(this.segments);
+
+ // Reset any highlight colours before updating.
+ helpers.each(this.activeElements, function(activeElement){
+ activeElement.restore(['fillColor']);
+ });
+
+ helpers.each(this.segments,function(segment){
+ segment.save();
+ });
+ this.render();
+ },
+
+ removeData: function(atIndex){
+ var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
+ this.segments.splice(indexToDelete, 1);
+ this.reflow();
+ this.update();
+ },
+
+ reflow : function(){
+ helpers.extend(this.SegmentArc.prototype,{
+ x : this.chart.width/2,
+ y : this.chart.height/2
+ });
+ this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
+ helpers.each(this.segments, function(segment){
+ segment.update({
+ outerRadius : this.outerRadius,
+ innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
+ });
+ }, this);
+ },
+ draw : function(easeDecimal){
+ var animDecimal = (easeDecimal) ? easeDecimal : 1;
+ this.clear();
+ helpers.each(this.segments,function(segment,index){
+ segment.transition({
+ circumference : this.calculateCircumference(segment.value),
+ outerRadius : this.outerRadius,
+ innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
+ },animDecimal);
+
+ segment.endAngle = segment.startAngle + segment.circumference;
+
+ segment.draw();
+ if (index === 0){
+ segment.startAngle = Math.PI * 1.5;
+ }
+ //Check to see if it's the last segment, if not get the next and update the start angle
+ if (index < this.segments.length-1){
+ this.segments[index+1].startAngle = segment.endAngle;
+ }
+ },this);
+
+ }
+ });
+
+ Chart.types.Doughnut.extend({
+ name : "Pie",
+ defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
+ });
+
+}).call(this);
+(function(){
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ helpers = Chart.helpers;
+
+ var defaultConfig = {
+
+ ///Boolean - Whether grid lines are shown across the chart
+ scaleShowGridLines : true,
+
+ //String - Colour of the grid lines
+ scaleGridLineColor : "rgba(0,0,0,.05)",
+
+ //Number - Width of the grid lines
+ scaleGridLineWidth : 1,
+
+ //Boolean - Whether to show horizontal lines (except X axis)
+ scaleShowHorizontalLines: true,
+
+ //Boolean - Whether to show vertical lines (except Y axis)
+ scaleShowVerticalLines: true,
+
+ //Boolean - Whether the line is curved between points
+ bezierCurve : true,
+
+ //Number - Tension of the bezier curve between points
+ bezierCurveTension : 0.4,
+
+ //Boolean - Whether to show a dot for each point
+ pointDot : true,
+
+ //Number - Radius of each point dot in pixels
+ pointDotRadius : 4,
+
+ //Number - Pixel width of point dot stroke
+ pointDotStrokeWidth : 1,
+
+ //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
+ pointHitDetectionRadius : 20,
+
+ //Boolean - Whether to show a stroke for datasets
+ datasetStroke : true,
+
+ //Number - Pixel width of dataset stroke
+ datasetStrokeWidth : 2,
+
+ //Boolean - Whether to fill the dataset with a colour
+ datasetFill : true,
+
+ //String - A legend template
+ legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
+
+ };
+
+
+ Chart.Type.extend({
+ name: "Line",
+ defaults : defaultConfig,
+ initialize: function(data){
+ //Declare the extension of the default point, to cater for the options passed in to the constructor
+ this.PointClass = Chart.Point.extend({
+ strokeWidth : this.options.pointDotStrokeWidth,
+ radius : this.options.pointDotRadius,
+ display: this.options.pointDot,
+ hitDetectionRadius : this.options.pointHitDetectionRadius,
+ ctx : this.chart.ctx,
+ inRange : function(mouseX){
+ return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));
+ }
+ });
+
+ this.datasets = [];
+
+ //Set up tooltip events on the chart
+ if (this.options.showTooltips){
+ helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
+ var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
+ this.eachPoints(function(point){
+ point.restore(['fillColor', 'strokeColor']);
+ });
+ helpers.each(activePoints, function(activePoint){
+ activePoint.fillColor = activePoint.highlightFill;
+ activePoint.strokeColor = activePoint.highlightStroke;
+ });
+ this.showTooltip(activePoints);
+ });
+ }
+
+ //Iterate through each of the datasets, and build this into a property of the chart
+ helpers.each(data.datasets,function(dataset){
+
+ var datasetObject = {
+ label : dataset.label || null,
+ fillColor : dataset.fillColor,
+ strokeColor : dataset.strokeColor,
+ pointColor : dataset.pointColor,
+ pointStrokeColor : dataset.pointStrokeColor,
+ points : []
+ };
+
+ this.datasets.push(datasetObject);
+
+
+ helpers.each(dataset.data,function(dataPoint,index){
+ //Add a new point for each piece of data, passing any required data to draw.
+ datasetObject.points.push(new this.PointClass({
+ value : dataPoint,
+ label : data.labels[index],
+ datasetLabel: dataset.label,
+ strokeColor : dataset.pointStrokeColor,
+ fillColor : dataset.pointColor,
+ highlightFill : dataset.pointHighlightFill || dataset.pointColor,
+ highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
+ }));
+ },this);
+
+ this.buildScale(data.labels);
+
+
+ this.eachPoints(function(point, index){
+ helpers.extend(point, {
+ x: this.scale.calculateX(index),
+ y: this.scale.endPoint
+ });
+ point.save();
+ }, this);
+
+ },this);
+
+
+ this.render();
+ },
+ update : function(){
+ this.scale.update();
+ // Reset any highlight colours before updating.
+ helpers.each(this.activeElements, function(activeElement){
+ activeElement.restore(['fillColor', 'strokeColor']);
+ });
+ this.eachPoints(function(point){
+ point.save();
+ });
+ this.render();
+ },
+ eachPoints : function(callback){
+ helpers.each(this.datasets,function(dataset){
+ helpers.each(dataset.points,callback,this);
+ },this);
+ },
+ getPointsAtEvent : function(e){
+ var pointsArray = [],
+ eventPosition = helpers.getRelativePosition(e);
+ helpers.each(this.datasets,function(dataset){
+ helpers.each(dataset.points,function(point){
+ if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);
+ });
+ },this);
+ return pointsArray;
+ },
+ buildScale : function(labels){
+ var self = this;
+
+ var dataTotal = function(){
+ var values = [];
+ self.eachPoints(function(point){
+ values.push(point.value);
+ });
+
+ return values;
+ };
+
+ var scaleOptions = {
+ templateString : this.options.scaleLabel,
+ height : this.chart.height,
+ width : this.chart.width,
+ ctx : this.chart.ctx,
+ textColor : this.options.scaleFontColor,
+ fontSize : this.options.scaleFontSize,
+ fontStyle : this.options.scaleFontStyle,
+ fontFamily : this.options.scaleFontFamily,
+ valuesCount : labels.length,
+ beginAtZero : this.options.scaleBeginAtZero,
+ integersOnly : this.options.scaleIntegersOnly,
+ calculateYRange : function(currentHeight){
+ var updatedRanges = helpers.calculateScaleRange(
+ dataTotal(),
+ currentHeight,
+ this.fontSize,
+ this.beginAtZero,
+ this.integersOnly
+ );
+ helpers.extend(this, updatedRanges);
+ },
+ xLabels : labels,
+ font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
+ lineWidth : this.options.scaleLineWidth,
+ lineColor : this.options.scaleLineColor,
+ showHorizontalLines : this.options.scaleShowHorizontalLines,
+ showVerticalLines : this.options.scaleShowVerticalLines,
+ gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
+ gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
+ padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
+ showLabels : this.options.scaleShowLabels,
+ display : this.options.showScale
+ };
+
+ if (this.options.scaleOverride){
+ helpers.extend(scaleOptions, {
+ calculateYRange: helpers.noop,
+ steps: this.options.scaleSteps,
+ stepValue: this.options.scaleStepWidth,
+ min: this.options.scaleStartValue,
+ max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
+ });
+ }
+
+
+ this.scale = new Chart.Scale(scaleOptions);
+ },
+ addData : function(valuesArray,label){
+ //Map the values array for each of the datasets
+
+ helpers.each(valuesArray,function(value,datasetIndex){
+ //Add a new point for each piece of data, passing any required data to draw.
+ this.datasets[datasetIndex].points.push(new this.PointClass({
+ value : value,
+ label : label,
+ x: this.scale.calculateX(this.scale.valuesCount+1),
+ y: this.scale.endPoint,
+ strokeColor : this.datasets[datasetIndex].pointStrokeColor,
+ fillColor : this.datasets[datasetIndex].pointColor
+ }));
+ },this);
+
+ this.scale.addXLabel(label);
+ //Then re-render the chart.
+ this.update();
+ },
+ removeData : function(){
+ this.scale.removeXLabel();
+ //Then re-render the chart.
+ helpers.each(this.datasets,function(dataset){
+ dataset.points.shift();
+ },this);
+ this.update();
+ },
+ reflow : function(){
+ var newScaleProps = helpers.extend({
+ height : this.chart.height,
+ width : this.chart.width
+ });
+ this.scale.update(newScaleProps);
+ },
+ draw : function(ease){
+ var easingDecimal = ease || 1;
+ this.clear();
+
+ var ctx = this.chart.ctx;
+
+ // Some helper methods for getting the next/prev points
+ var hasValue = function(item){
+ return item.value !== null;
+ },
+ nextPoint = function(point, collection, index){
+ return helpers.findNextWhere(collection, hasValue, index) || point;
+ },
+ previousPoint = function(point, collection, index){
+ return helpers.findPreviousWhere(collection, hasValue, index) || point;
+ };
+
+ this.scale.draw(easingDecimal);
+
+
+ helpers.each(this.datasets,function(dataset){
+ var pointsWithValues = helpers.where(dataset.points, hasValue);
+
+ //Transition each point first so that the line and point drawing isn't out of sync
+ //We can use this extra loop to calculate the control points of this dataset also in this loop
+
+ helpers.each(dataset.points, function(point, index){
+ if (point.hasValue()){
+ point.transition({
+ y : this.scale.calculateY(point.value),
+ x : this.scale.calculateX(index)
+ }, easingDecimal);
+ }
+ },this);
+
+
+ // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
+ // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
+ if (this.options.bezierCurve){
+ helpers.each(pointsWithValues, function(point, index){
+ var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;
+ point.controlPoints = helpers.splineCurve(
+ previousPoint(point, pointsWithValues, index),
+ point,
+ nextPoint(point, pointsWithValues, index),
+ tension
+ );
+
+ // Prevent the bezier going outside of the bounds of the graph
+
+ // Cap puter bezier handles to the upper/lower scale bounds
+ if (point.controlPoints.outer.y > this.scale.endPoint){
+ point.controlPoints.outer.y = this.scale.endPoint;
+ }
+ else if (point.controlPoints.outer.y < this.scale.startPoint){
+ point.controlPoints.outer.y = this.scale.startPoint;
+ }
+
+ // Cap inner bezier handles to the upper/lower scale bounds
+ if (point.controlPoints.inner.y > this.scale.endPoint){
+ point.controlPoints.inner.y = this.scale.endPoint;
+ }
+ else if (point.controlPoints.inner.y < this.scale.startPoint){
+ point.controlPoints.inner.y = this.scale.startPoint;
+ }
+ },this);
+ }
+
+
+ //Draw the line between all the points
+ ctx.lineWidth = this.options.datasetStrokeWidth;
+ ctx.strokeStyle = dataset.strokeColor;
+ ctx.beginPath();
+
+ helpers.each(pointsWithValues, function(point, index){
+ if (index === 0){
+ ctx.moveTo(point.x, point.y);
+ }
+ else{
+ if(this.options.bezierCurve){
+ var previous = previousPoint(point, pointsWithValues, index);
+
+ ctx.bezierCurveTo(
+ previous.controlPoints.outer.x,
+ previous.controlPoints.outer.y,
+ point.controlPoints.inner.x,
+ point.controlPoints.inner.y,
+ point.x,
+ point.y
+ );
+ }
+ else{
+ ctx.lineTo(point.x,point.y);
+ }
+ }
+ }, this);
+
+ ctx.stroke();
+
+ if (this.options.datasetFill && pointsWithValues.length > 0){
+ //Round off the line by going to the base of the chart, back to the start, then fill.
+ ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);
+ ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);
+ ctx.fillStyle = dataset.fillColor;
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ //Now draw the points over the line
+ //A little inefficient double looping, but better than the line
+ //lagging behind the point positions
+ helpers.each(pointsWithValues,function(point){
+ point.draw();
+ });
+ },this);
+ }
+ });
+
+
+}).call(this);
+
+(function(){
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ //Cache a local reference to Chart.helpers
+ helpers = Chart.helpers;
+
+ var defaultConfig = {
+ //Boolean - Show a backdrop to the scale label
+ scaleShowLabelBackdrop : true,
+
+ //String - The colour of the label backdrop
+ scaleBackdropColor : "rgba(255,255,255,0.75)",
+
+ // Boolean - Whether the scale should begin at zero
+ scaleBeginAtZero : true,
+
+ //Number - The backdrop padding above & below the label in pixels
+ scaleBackdropPaddingY : 2,
+
+ //Number - The backdrop padding to the side of the label in pixels
+ scaleBackdropPaddingX : 2,
+
+ //Boolean - Show line for each value in the scale
+ scaleShowLine : true,
+
+ //Boolean - Stroke a line around each segment in the chart
+ segmentShowStroke : true,
+
+ //String - The colour of the stroke on each segement.
+ segmentStrokeColor : "#fff",
+
+ //Number - The width of the stroke value in pixels
+ segmentStrokeWidth : 2,
+
+ //Number - Amount of animation steps
+ animationSteps : 100,
+
+ //String - Animation easing effect.
+ animationEasing : "easeOutBounce",
+
+ //Boolean - Whether to animate the rotation of the chart
+ animateRotate : true,
+
+ //Boolean - Whether to animate scaling the chart from the centre
+ animateScale : false,
+
+ //String - A legend template
+ legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
+ };
+
+
+ Chart.Type.extend({
+ //Passing in a name registers this chart in the Chart namespace
+ name: "PolarArea",
+ //Providing a defaults will also register the deafults in the chart namespace
+ defaults : defaultConfig,
+ //Initialize is fired when the chart is initialized - Data is passed in as a parameter
+ //Config is automatically merged by the core of Chart.js, and is available at this.options
+ initialize: function(data){
+ this.segments = [];
+ //Declare segment class as a chart instance specific class, so it can share props for this instance
+ this.SegmentArc = Chart.Arc.extend({
+ showStroke : this.options.segmentShowStroke,
+ strokeWidth : this.options.segmentStrokeWidth,
+ strokeColor : this.options.segmentStrokeColor,
+ ctx : this.chart.ctx,
+ innerRadius : 0,
+ x : this.chart.width/2,
+ y : this.chart.height/2
+ });
+ this.scale = new Chart.RadialScale({
+ display: this.options.showScale,
+ fontStyle: this.options.scaleFontStyle,
+ fontSize: this.options.scaleFontSize,
+ fontFamily: this.options.scaleFontFamily,
+ fontColor: this.options.scaleFontColor,
+ showLabels: this.options.scaleShowLabels,
+ showLabelBackdrop: this.options.scaleShowLabelBackdrop,
+ backdropColor: this.options.scaleBackdropColor,
+ backdropPaddingY : this.options.scaleBackdropPaddingY,
+ backdropPaddingX: this.options.scaleBackdropPaddingX,
+ lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
+ lineColor: this.options.scaleLineColor,
+ lineArc: true,
+ width: this.chart.width,
+ height: this.chart.height,
+ xCenter: this.chart.width/2,
+ yCenter: this.chart.height/2,
+ ctx : this.chart.ctx,
+ templateString: this.options.scaleLabel,
+ valuesCount: data.length
+ });
+
+ this.updateScaleRange(data);
+
+ this.scale.update();
+
+ helpers.each(data,function(segment,index){
+ this.addData(segment,index,true);
+ },this);
+
+ //Set up tooltip events on the chart
+ if (this.options.showTooltips){
+ helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
+ var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
+ helpers.each(this.segments,function(segment){
+ segment.restore(["fillColor"]);
+ });
+ helpers.each(activeSegments,function(activeSegment){
+ activeSegment.fillColor = activeSegment.highlightColor;
+ });
+ this.showTooltip(activeSegments);
+ });
+ }
+
+ this.render();
+ },
+ getSegmentsAtEvent : function(e){
+ var segmentsArray = [];
+
+ var location = helpers.getRelativePosition(e);
+
+ helpers.each(this.segments,function(segment){
+ if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
+ },this);
+ return segmentsArray;
+ },
+ addData : function(segment, atIndex, silent){
+ var index = atIndex || this.segments.length;
+
+ this.segments.splice(index, 0, new this.SegmentArc({
+ fillColor: segment.color,
+ highlightColor: segment.highlight || segment.color,
+ label: segment.label,
+ value: segment.value,
+ outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
+ circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
+ startAngle: Math.PI * 1.5
+ }));
+ if (!silent){
+ this.reflow();
+ this.update();
+ }
+ },
+ removeData: function(atIndex){
+ var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
+ this.segments.splice(indexToDelete, 1);
+ this.reflow();
+ this.update();
+ },
+ calculateTotal: function(data){
+ this.total = 0;
+ helpers.each(data,function(segment){
+ this.total += segment.value;
+ },this);
+ this.scale.valuesCount = this.segments.length;
+ },
+ updateScaleRange: function(datapoints){
+ var valuesArray = [];
+ helpers.each(datapoints,function(segment){
+ valuesArray.push(segment.value);
+ });
+
+ var scaleSizes = (this.options.scaleOverride) ?
+ {
+ steps: this.options.scaleSteps,
+ stepValue: this.options.scaleStepWidth,
+ min: this.options.scaleStartValue,
+ max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
+ } :
+ helpers.calculateScaleRange(
+ valuesArray,
+ helpers.min([this.chart.width, this.chart.height])/2,
+ this.options.scaleFontSize,
+ this.options.scaleBeginAtZero,
+ this.options.scaleIntegersOnly
+ );
+
+ helpers.extend(
+ this.scale,
+ scaleSizes,
+ {
+ size: helpers.min([this.chart.width, this.chart.height]),
+ xCenter: this.chart.width/2,
+ yCenter: this.chart.height/2
+ }
+ );
+
+ },
+ update : function(){
+ this.calculateTotal(this.segments);
+
+ helpers.each(this.segments,function(segment){
+ segment.save();
+ });
+
+ this.reflow();
+ this.render();
+ },
+ reflow : function(){
+ helpers.extend(this.SegmentArc.prototype,{
+ x : this.chart.width/2,
+ y : this.chart.height/2
+ });
+ this.updateScaleRange(this.segments);
+ this.scale.update();
+
+ helpers.extend(this.scale,{
+ xCenter: this.chart.width/2,
+ yCenter: this.chart.height/2
+ });
+
+ helpers.each(this.segments, function(segment){
+ segment.update({
+ outerRadius : this.scale.calculateCenterOffset(segment.value)
+ });
+ }, this);
+
+ },
+ draw : function(ease){
+ var easingDecimal = ease || 1;
+ //Clear & draw the canvas
+ this.clear();
+ helpers.each(this.segments,function(segment, index){
+ segment.transition({
+ circumference : this.scale.getCircumference(),
+ outerRadius : this.scale.calculateCenterOffset(segment.value)
+ },easingDecimal);
+
+ segment.endAngle = segment.startAngle + segment.circumference;
+
+ // If we've removed the first segment we need to set the first one to
+ // start at the top.
+ if (index === 0){
+ segment.startAngle = Math.PI * 1.5;
+ }
+
+ //Check to see if it's the last segment, if not get the next and update the start angle
+ if (index < this.segments.length - 1){
+ this.segments[index+1].startAngle = segment.endAngle;
+ }
+ segment.draw();
+ }, this);
+ this.scale.draw();
+ }
+ });
+
+}).call(this);
+(function(){
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ helpers = Chart.helpers;
+
+
+
+ Chart.Type.extend({
+ name: "Radar",
+ defaults:{
+ //Boolean - Whether to show lines for each scale point
+ scaleShowLine : true,
+
+ //Boolean - Whether we show the angle lines out of the radar
+ angleShowLineOut : true,
+
+ //Boolean - Whether to show labels on the scale
+ scaleShowLabels : false,
+
+ // Boolean - Whether the scale should begin at zero
+ scaleBeginAtZero : true,
+
+ //String - Colour of the angle line
+ angleLineColor : "rgba(0,0,0,.1)",
+
+ //Number - Pixel width of the angle line
+ angleLineWidth : 1,
+
+ //String - Point label font declaration
+ pointLabelFontFamily : "'Arial'",
+
+ //String - Point label font weight
+ pointLabelFontStyle : "normal",
+
+ //Number - Point label font size in pixels
+ pointLabelFontSize : 10,
+
+ //String - Point label font colour
+ pointLabelFontColor : "#666",
+
+ //Boolean - Whether to show a dot for each point
+ pointDot : true,
+
+ //Number - Radius of each point dot in pixels
+ pointDotRadius : 3,
+
+ //Number - Pixel width of point dot stroke
+ pointDotStrokeWidth : 1,
+
+ //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
+ pointHitDetectionRadius : 20,
+
+ //Boolean - Whether to show a stroke for datasets
+ datasetStroke : true,
+
+ //Number - Pixel width of dataset stroke
+ datasetStrokeWidth : 2,
+
+ //Boolean - Whether to fill the dataset with a colour
+ datasetFill : true,
+
+ //String - A legend template
+ legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
+
+ },
+
+ initialize: function(data){
+ this.PointClass = Chart.Point.extend({
+ strokeWidth : this.options.pointDotStrokeWidth,
+ radius : this.options.pointDotRadius,
+ display: this.options.pointDot,
+ hitDetectionRadius : this.options.pointHitDetectionRadius,
+ ctx : this.chart.ctx
+ });
+
+ this.datasets = [];
+
+ this.buildScale(data);
+
+ //Set up tooltip events on the chart
+ if (this.options.showTooltips){
+ helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
+ var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
+
+ this.eachPoints(function(point){
+ point.restore(['fillColor', 'strokeColor']);
+ });
+ helpers.each(activePointsCollection, function(activePoint){
+ activePoint.fillColor = activePoint.highlightFill;
+ activePoint.strokeColor = activePoint.highlightStroke;
+ });
+
+ this.showTooltip(activePointsCollection);
+ });
+ }
+
+ //Iterate through each of the datasets, and build this into a property of the chart
+ helpers.each(data.datasets,function(dataset){
+
+ var datasetObject = {
+ label: dataset.label || null,
+ fillColor : dataset.fillColor,
+ strokeColor : dataset.strokeColor,
+ pointColor : dataset.pointColor,
+ pointStrokeColor : dataset.pointStrokeColor,
+ points : []
+ };
+
+ this.datasets.push(datasetObject);
+
+ helpers.each(dataset.data,function(dataPoint,index){
+ //Add a new point for each piece of data, passing any required data to draw.
+ var pointPosition;
+ if (!this.scale.animation){
+ pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
+ }
+ datasetObject.points.push(new this.PointClass({
+ value : dataPoint,
+ label : data.labels[index],
+ datasetLabel: dataset.label,
+ x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
+ y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
+ strokeColor : dataset.pointStrokeColor,
+ fillColor : dataset.pointColor,
+ highlightFill : dataset.pointHighlightFill || dataset.pointColor,
+ highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
+ }));
+ },this);
+
+ },this);
+
+ this.render();
+ },
+ eachPoints : function(callback){
+ helpers.each(this.datasets,function(dataset){
+ helpers.each(dataset.points,callback,this);
+ },this);
+ },
+
+ getPointsAtEvent : function(evt){
+ var mousePosition = helpers.getRelativePosition(evt),
+ fromCenter = helpers.getAngleFromPoint({
+ x: this.scale.xCenter,
+ y: this.scale.yCenter
+ }, mousePosition);
+
+ var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
+ pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
+ activePointsCollection = [];
+
+ // If we're at the top, make the pointIndex 0 to get the first of the array.
+ if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
+ pointIndex = 0;
+ }
+
+ if (fromCenter.distance <= this.scale.drawingArea){
+ helpers.each(this.datasets, function(dataset){
+ activePointsCollection.push(dataset.points[pointIndex]);
+ });
+ }
+
+ return activePointsCollection;
+ },
+
+ buildScale : function(data){
+ this.scale = new Chart.RadialScale({
+ display: this.options.showScale,
+ fontStyle: this.options.scaleFontStyle,
+ fontSize: this.options.scaleFontSize,
+ fontFamily: this.options.scaleFontFamily,
+ fontColor: this.options.scaleFontColor,
+ showLabels: this.options.scaleShowLabels,
+ showLabelBackdrop: this.options.scaleShowLabelBackdrop,
+ backdropColor: this.options.scaleBackdropColor,
+ backdropPaddingY : this.options.scaleBackdropPaddingY,
+ backdropPaddingX: this.options.scaleBackdropPaddingX,
+ lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
+ lineColor: this.options.scaleLineColor,
+ angleLineColor : this.options.angleLineColor,
+ angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
+ // Point labels at the edge of each line
+ pointLabelFontColor : this.options.pointLabelFontColor,
+ pointLabelFontSize : this.options.pointLabelFontSize,
+ pointLabelFontFamily : this.options.pointLabelFontFamily,
+ pointLabelFontStyle : this.options.pointLabelFontStyle,
+ height : this.chart.height,
+ width: this.chart.width,
+ xCenter: this.chart.width/2,
+ yCenter: this.chart.height/2,
+ ctx : this.chart.ctx,
+ templateString: this.options.scaleLabel,
+ labels: data.labels,
+ valuesCount: data.datasets[0].data.length
+ });
+
+ this.scale.setScaleSize();
+ this.updateScaleRange(data.datasets);
+ this.scale.buildYLabels();
+ },
+ updateScaleRange: function(datasets){
+ var valuesArray = (function(){
+ var totalDataArray = [];
+ helpers.each(datasets,function(dataset){
+ if (dataset.data){
+ totalDataArray = totalDataArray.concat(dataset.data);
+ }
+ else {
+ helpers.each(dataset.points, function(point){
+ totalDataArray.push(point.value);
+ });
+ }
+ });
+ return totalDataArray;
+ })();
+
+
+ var scaleSizes = (this.options.scaleOverride) ?
+ {
+ steps: this.options.scaleSteps,
+ stepValue: this.options.scaleStepWidth,
+ min: this.options.scaleStartValue,
+ max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
+ } :
+ helpers.calculateScaleRange(
+ valuesArray,
+ helpers.min([this.chart.width, this.chart.height])/2,
+ this.options.scaleFontSize,
+ this.options.scaleBeginAtZero,
+ this.options.scaleIntegersOnly
+ );
+
+ helpers.extend(
+ this.scale,
+ scaleSizes
+ );
+
+ },
+ addData : function(valuesArray,label){
+ //Map the values array for each of the datasets
+ this.scale.valuesCount++;
+ helpers.each(valuesArray,function(value,datasetIndex){
+ var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
+ this.datasets[datasetIndex].points.push(new this.PointClass({
+ value : value,
+ label : label,
+ x: pointPosition.x,
+ y: pointPosition.y,
+ strokeColor : this.datasets[datasetIndex].pointStrokeColor,
+ fillColor : this.datasets[datasetIndex].pointColor
+ }));
+ },this);
+
+ this.scale.labels.push(label);
+
+ this.reflow();
+
+ this.update();
+ },
+ removeData : function(){
+ this.scale.valuesCount--;
+ this.scale.labels.shift();
+ helpers.each(this.datasets,function(dataset){
+ dataset.points.shift();
+ },this);
+ this.reflow();
+ this.update();
+ },
+ update : function(){
+ this.eachPoints(function(point){
+ point.save();
+ });
+ this.reflow();
+ this.render();
+ },
+ reflow: function(){
+ helpers.extend(this.scale, {
+ width : this.chart.width,
+ height: this.chart.height,
+ size : helpers.min([this.chart.width, this.chart.height]),
+ xCenter: this.chart.width/2,
+ yCenter: this.chart.height/2
+ });
+ this.updateScaleRange(this.datasets);
+ this.scale.setScaleSize();
+ this.scale.buildYLabels();
+ },
+ draw : function(ease){
+ var easeDecimal = ease || 1,
+ ctx = this.chart.ctx;
+ this.clear();
+ this.scale.draw();
+
+ helpers.each(this.datasets,function(dataset){
+
+ //Transition each point first so that the line and point drawing isn't out of sync
+ helpers.each(dataset.points,function(point,index){
+ if (point.hasValue()){
+ point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
+ }
+ },this);
+
+
+
+ //Draw the line between all the points
+ ctx.lineWidth = this.options.datasetStrokeWidth;
+ ctx.strokeStyle = dataset.strokeColor;
+ ctx.beginPath();
+ helpers.each(dataset.points,function(point,index){
+ if (index === 0){
+ ctx.moveTo(point.x,point.y);
+ }
+ else{
+ ctx.lineTo(point.x,point.y);
+ }
+ },this);
+ ctx.closePath();
+ ctx.stroke();
+
+ ctx.fillStyle = dataset.fillColor;
+ ctx.fill();
+
+ //Now draw the points over the line
+ //A little inefficient double looping, but better than the line
+ //lagging behind the point positions
+ helpers.each(dataset.points,function(point){
+ if (point.hasValue()){
+ point.draw();
+ }
+ });
+
+ },this);
+
+ }
+
+ });
+
+
+
+
+
+}).call(this); \ No newline at end of file
diff --git a/vendor/assets/javascripts/chart-lib.min.js b/vendor/assets/javascripts/chart-lib.min.js
deleted file mode 100644
index 3a0a2c87345..00000000000
--- a/vendor/assets/javascripts/chart-lib.min.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*!
- * Chart.js
- * http://chartjs.org/
- * Version: 1.0.2
- *
- * Copyright 2015 Nick Downie
- * Released under the MIT license
- * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
- */
-(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;var i=function(t,i){return t["offset"+i]?t["offset"+i]:document.defaultView.getComputedStyle(t).getPropertyValue(i)},e=this.width=i(t.canvas,"Width"),n=this.height=i(t.canvas,"Height");t.canvas.width=e,t.canvas.height=n;var e=this.width=t.canvas.width,n=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n<t.length;n++)i.apply(e,[t[n],n].concat(s))}else for(var o in t)i.apply(e,[t[o],o].concat(s))},o=s.clone=function(t){var i={};return n(t,function(e,s){t.hasOwnProperty(s)&&(i[s]=e)}),i},a=s.extend=function(t){return n(Array.prototype.slice.call(arguments,1),function(i){n(i,function(e,s){i.hasOwnProperty(s)&&(t[s]=e)})}),t},h=s.merge=function(){var t=Array.prototype.slice.call(arguments,0);return t.unshift({}),a.apply(null,t)},l=s.indexOf=function(t,i){if(Array.prototype.indexOf)return t.indexOf(i);for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1},r=(s.where=function(t,i){var e=[];return s.each(t,function(t){i(t)&&e.push(t)}),e},s.findNextWhere=function(t,i,e){e||(e=-1);for(var s=e+1;s<t.length;s++){var n=t[s];if(i(n))return n}},s.findPreviousWhere=function(t,i,e){e||(e=t.length);for(var s=e-1;s>=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof define&&define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),S=s.radians=function(t){return t*(Math.PI/180)},x=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),S=Math.round(f/v);(S>a||a>2*S)&&!h;)if(S>a)v*=2,S=Math.round(f/v),S%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,S=Math.round(f/v)}else v/=2,S=Math.round(f/v);return h&&(S=o,v=f/S),{steps:S,stepValue:v,min:p,max:p+S*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),w=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),-(s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)))},easeOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),s*Math.pow(2,-10*t)*Math.sin(2*(1*t-i)*Math.PI/e)+1)},easeInOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:2==(t/=.5)?1:(e||(e=.3*1.5),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),1>t?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-w.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*w.easeInBounce(2*t):.5*w.easeOutBounce(2*t-1)+.5}}),b=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),L=(s.animationLoop=function(t,i,e,s,n,o){var a=0,h=w[e]||w.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=b(l):n.apply(o)};b(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),k=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},F=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},L(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){k(t.chart.canvas,e,i)})}),R=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},T=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),M=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},W=s.fontString=function(t,i,e){return i+" "+t+"px "+e},z=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},B=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return M(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=R(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:T(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),F(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)<Math.pow(e,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),e.Arc=e.Element.extend({inRange:function(t,i){var e=s.getAngleFromPoint(this,{x:t,y:i}),n=e.angle>=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=this.caretPadding=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}B(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=W(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=z(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{B(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?z(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()},calculateXLabelRotation:function(){this.ctx.font=this.font;var t,i,e=this.ctx.measureText(this.xLabels[0]).width,s=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=s/2+3,this.xScalePaddingLeft=e/2>this.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=z(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(S(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(S(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),l&&(t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+x(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+x(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==e||a||(a=!0),a&&t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*S(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;i<this.valuesCount;i++)t=this.getPointPosition(i,d),e=this.ctx.measureText(C(this.templateString,{value:this.labels[i]})).width+5,0===i||i===this.valuesCount/2?(s=e/2,t.x+s>p&&(p=t.x+s,n=i),t.x-s<g&&(g=t.x-s,a=i)):i<this.valuesCount/2?t.x+e>p&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e<g&&(g=t.x-e,a=i);l=g,r=Math.ceil(p-this.width),o=this.getIndexAngle(n),h=this.getIndexAngle(a),c=r/Math.sin(o+Math.PI/2),u=l/Math.sin(h+Math.PI/2),c=f(c)?c:0,u=f(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,i){var e=this.width-i-this.drawingArea,s=t+this.drawingArea;this.xCenter=(s+e)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var i=2*Math.PI/this.valuesCount;return t*i-Math.PI/2},getPointPosition:function(t,i){var e=this.getIndexAngle(t);return{x:Math.cos(e)*i+this.xCenter,y:Math.sin(e)*i+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(n(this.yLabels,function(i,e){if(e>0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)s=this.getPointPosition(a,this.calculateCenterOffset(this.min+e*this.stepValue)),0===a?t.moveTo(s.x,s.y):t.lineTo(s.x,s.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var h=t.measureText(i).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-h/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,h+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(i,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var i=this.valuesCount-1;i>=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<this.datasets.length;a++)for(i=0;i<this.datasets[a].bars.length;i++)if(this.datasets[a].bars[i].inRange(n.x,n.y))return e.each(this.datasets,o),s;return s},buildScale:function(t){var i=this,s=function(){var t=[];return i.eachBars(function(i){t.push(i.value)}),t},n={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(n,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(n)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].bars.push(new this.BarClass({value:t,label:i,x:this.scale.calculateBarX(this.datasets.length,e,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),base:this.scale.endPoint,strokeColor:this.datasets[e].strokeColor,fillColor:this.datasets[e].fillColor}))
-},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle)},this)}}),i.types.Doughnut.extend({name:"Pie",defaults:e.merge(s,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,i){e.extend(t,{x:this.scale.calculateX(i),y:this.scale.endPoint}),t.save()},this)},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.datasets,function(t){e.each(t.points,function(t){t.inRange(s.x,s.y)&&i.push(t)})},this),i},buildScale:function(t){var s=this,n=function(){var t=[];return s.eachPoints(function(i){t.push(i.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(o,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new i.Scale(o)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();var s=this.chart.ctx,n=function(t){return null!==t.value},o=function(t,i,s){return e.findNextWhere(i,n,s)||t},a=function(t,i,s){return e.findPreviousWhere(i,n,s)||t};this.scale.draw(i),e.each(this.datasets,function(t){var h=e.where(t.points,n);e.each(t.points,function(t,e){t.hasValue()&&t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(e)},i)},this),this.options.bezierCurve&&e.each(h,function(t,i){var s=i>0&&i<h.length-1?this.options.bezierCurveTension:0;t.controlPoints=e.splineCurve(a(t,h,i),t,o(t,h,i),s),t.controlPoints.outer.y>this.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.y<this.scale.startPoint&&(t.controlPoints.outer.y=this.scale.startPoint),t.controlPoints.inner.y>this.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y<this.scale.startPoint&&(t.controlPoints.inner.y=this.scale.startPoint)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(h,function(t,i){if(0===i)s.moveTo(t.x,t.y);else if(this.options.bezierCurve){var e=a(t,h,i);s.bezierCurveTo(e.controlPoints.outer.x,e.controlPoints.outer.y,t.controlPoints.inner.x,t.controlPoints.inner.y,t.x,t.y)}else s.lineTo(t.x,t.y)},this),s.stroke(),this.options.datasetFill&&h.length>0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers;i.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); \ No newline at end of file
diff --git a/vendor/assets/javascripts/fuzzaldrin-plus.js b/vendor/assets/javascripts/fuzzaldrin-plus.js
new file mode 100644
index 00000000000..1985e3f8f6c
--- /dev/null
+++ b/vendor/assets/javascripts/fuzzaldrin-plus.js
@@ -0,0 +1,1161 @@
+/*!
+ * fuzzaldrin-plus.js - 0.3.1
+ * https://github.com/jeancroy/fuzzaldrin-plus
+ *
+ * Copyright 2016 - Jean Christophe Roy
+ * Released under the MIT license
+ * https://github.com/jeancroy/fuzzaldrin-plus/raw/master/LICENSE.md
+ */
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+fuzzaldrinPlus = require('fuzzaldrin-plus');
+
+},{"fuzzaldrin-plus":3}],2:[function(require,module,exports){
+(function() {
+ var PathSeparator, legacy_scorer, pluckCandidates, scorer, sortCandidates;
+
+ scorer = require('./scorer');
+
+ legacy_scorer = require('./legacy');
+
+ pluckCandidates = function(a) {
+ return a.candidate;
+ };
+
+ sortCandidates = function(a, b) {
+ return b.score - a.score;
+ };
+
+ PathSeparator = require('path').sep;
+
+ module.exports = function(candidates, query, _arg) {
+ var allowErrors, bAllowErrors, bKey, candidate, coreQuery, key, legacy, maxInners, maxResults, prepQuery, queryHasSlashes, score, scoredCandidates, spotLeft, string, _i, _j, _len, _len1, _ref;
+ _ref = _arg != null ? _arg : {}, key = _ref.key, maxResults = _ref.maxResults, maxInners = _ref.maxInners, allowErrors = _ref.allowErrors, legacy = _ref.legacy;
+ scoredCandidates = [];
+ spotLeft = (maxInners != null) && maxInners > 0 ? maxInners : candidates.length;
+ bAllowErrors = !!allowErrors;
+ bKey = key != null;
+ prepQuery = scorer.prepQuery(query);
+ if (!legacy) {
+ for (_i = 0, _len = candidates.length; _i < _len; _i++) {
+ candidate = candidates[_i];
+ string = bKey ? candidate[key] : candidate;
+ if (!string) {
+ continue;
+ }
+ score = scorer.score(string, query, prepQuery, bAllowErrors);
+ if (score > 0) {
+ scoredCandidates.push({
+ candidate: candidate,
+ score: score
+ });
+ if (!--spotLeft) {
+ break;
+ }
+ }
+ }
+ } else {
+ queryHasSlashes = prepQuery.depth > 0;
+ coreQuery = prepQuery.core;
+ for (_j = 0, _len1 = candidates.length; _j < _len1; _j++) {
+ candidate = candidates[_j];
+ string = key != null ? candidate[key] : candidate;
+ if (!string) {
+ continue;
+ }
+ score = legacy_scorer.score(string, coreQuery, queryHasSlashes);
+ if (!queryHasSlashes) {
+ score = legacy_scorer.basenameScore(string, coreQuery, score);
+ }
+ if (score > 0) {
+ scoredCandidates.push({
+ candidate: candidate,
+ score: score
+ });
+ }
+ }
+ }
+ scoredCandidates.sort(sortCandidates);
+ candidates = scoredCandidates.map(pluckCandidates);
+ if (maxResults != null) {
+ candidates = candidates.slice(0, maxResults);
+ }
+ return candidates;
+ };
+
+}).call(this);
+
+},{"./legacy":4,"./scorer":6,"path":7}],3:[function(require,module,exports){
+(function() {
+ var PathSeparator, filter, legacy_scorer, matcher, prepQueryCache, scorer;
+
+ scorer = require('./scorer');
+
+ legacy_scorer = require('./legacy');
+
+ filter = require('./filter');
+
+ matcher = require('./matcher');
+
+ PathSeparator = require('path').sep;
+
+ prepQueryCache = null;
+
+ module.exports = {
+ filter: function(candidates, query, options) {
+ if (!((query != null ? query.length : void 0) && (candidates != null ? candidates.length : void 0))) {
+ return [];
+ }
+ return filter(candidates, query, options);
+ },
+ prepQuery: function(query) {
+ return scorer.prepQuery(query);
+ },
+ score: function(string, query, prepQuery, _arg) {
+ var allowErrors, coreQuery, legacy, queryHasSlashes, score, _ref;
+ _ref = _arg != null ? _arg : {}, allowErrors = _ref.allowErrors, legacy = _ref.legacy;
+ if (!((string != null ? string.length : void 0) && (query != null ? query.length : void 0))) {
+ return 0;
+ }
+ if (prepQuery == null) {
+ prepQuery = prepQueryCache && prepQueryCache.query === query ? prepQueryCache : (prepQueryCache = scorer.prepQuery(query));
+ }
+ if (!legacy) {
+ score = scorer.score(string, query, prepQuery, !!allowErrors);
+ } else {
+ queryHasSlashes = prepQuery.depth > 0;
+ coreQuery = prepQuery.core;
+ score = legacy_scorer.score(string, coreQuery, queryHasSlashes);
+ if (!queryHasSlashes) {
+ score = legacy_scorer.basenameScore(string, coreQuery, score);
+ }
+ }
+ return score;
+ },
+ match: function(string, query, prepQuery, _arg) {
+ var allowErrors, baseMatches, matches, query_lw, string_lw, _i, _ref, _results;
+ allowErrors = (_arg != null ? _arg : {}).allowErrors;
+ if (!string) {
+ return [];
+ }
+ if (!query) {
+ return [];
+ }
+ if (string === query) {
+ return (function() {
+ _results = [];
+ for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }
+ return _results;
+ }).apply(this);
+ }
+ if (prepQuery == null) {
+ prepQuery = prepQueryCache && prepQueryCache.query === query ? prepQueryCache : (prepQueryCache = scorer.prepQuery(query));
+ }
+ if (!(allowErrors || scorer.isMatch(string, prepQuery.core_lw, prepQuery.core_up))) {
+ return [];
+ }
+ string_lw = string.toLowerCase();
+ query_lw = prepQuery.query_lw;
+ matches = matcher.match(string, string_lw, prepQuery);
+ if (matches.length === 0) {
+ return matches;
+ }
+ if (string.indexOf(PathSeparator) > -1) {
+ baseMatches = matcher.basenameMatch(string, string_lw, prepQuery);
+ matches = matcher.mergeMatches(matches, baseMatches);
+ }
+ return matches;
+ }
+ };
+
+}).call(this);
+
+},{"./filter":2,"./legacy":4,"./matcher":5,"./scorer":6,"path":7}],4:[function(require,module,exports){
+(function() {
+ var PathSeparator, queryIsLastPathSegment;
+
+ PathSeparator = require('path').sep;
+
+ exports.basenameScore = function(string, query, score) {
+ var base, depth, index, lastCharacter, segmentCount, slashCount;
+ index = string.length - 1;
+ while (string[index] === PathSeparator) {
+ index--;
+ }
+ slashCount = 0;
+ lastCharacter = index;
+ base = null;
+ while (index >= 0) {
+ if (string[index] === PathSeparator) {
+ slashCount++;
+ if (base == null) {
+ base = string.substring(index + 1, lastCharacter + 1);
+ }
+ } else if (index === 0) {
+ if (lastCharacter < string.length - 1) {
+ if (base == null) {
+ base = string.substring(0, lastCharacter + 1);
+ }
+ } else {
+ if (base == null) {
+ base = string;
+ }
+ }
+ }
+ index--;
+ }
+ if (base === string) {
+ score *= 2;
+ } else if (base) {
+ score += exports.score(base, query);
+ }
+ segmentCount = slashCount + 1;
+ depth = Math.max(1, 10 - segmentCount);
+ score *= depth * 0.01;
+ return score;
+ };
+
+ exports.score = function(string, query) {
+ var character, characterScore, indexInQuery, indexInString, lowerCaseIndex, minIndex, queryLength, queryScore, stringLength, totalCharacterScore, upperCaseIndex, _ref;
+ if (string === query) {
+ return 1;
+ }
+ if (queryIsLastPathSegment(string, query)) {
+ return 1;
+ }
+ totalCharacterScore = 0;
+ queryLength = query.length;
+ stringLength = string.length;
+ indexInQuery = 0;
+ indexInString = 0;
+ while (indexInQuery < queryLength) {
+ character = query[indexInQuery++];
+ lowerCaseIndex = string.indexOf(character.toLowerCase());
+ upperCaseIndex = string.indexOf(character.toUpperCase());
+ minIndex = Math.min(lowerCaseIndex, upperCaseIndex);
+ if (minIndex === -1) {
+ minIndex = Math.max(lowerCaseIndex, upperCaseIndex);
+ }
+ indexInString = minIndex;
+ if (indexInString === -1) {
+ return 0;
+ }
+ characterScore = 0.1;
+ if (string[indexInString] === character) {
+ characterScore += 0.1;
+ }
+ if (indexInString === 0 || string[indexInString - 1] === PathSeparator) {
+ characterScore += 0.8;
+ } else if ((_ref = string[indexInString - 1]) === '-' || _ref === '_' || _ref === ' ') {
+ characterScore += 0.7;
+ }
+ string = string.substring(indexInString + 1, stringLength);
+ totalCharacterScore += characterScore;
+ }
+ queryScore = totalCharacterScore / queryLength;
+ return ((queryScore * (queryLength / stringLength)) + queryScore) / 2;
+ };
+
+ queryIsLastPathSegment = function(string, query) {
+ if (string[string.length - query.length - 1] === PathSeparator) {
+ return string.lastIndexOf(query) === string.length - query.length;
+ }
+ };
+
+ exports.match = function(string, query, stringOffset) {
+ var character, indexInQuery, indexInString, lowerCaseIndex, matches, minIndex, queryLength, stringLength, upperCaseIndex, _i, _ref, _results;
+ if (stringOffset == null) {
+ stringOffset = 0;
+ }
+ if (string === query) {
+ return (function() {
+ _results = [];
+ for (var _i = stringOffset, _ref = stringOffset + string.length; stringOffset <= _ref ? _i < _ref : _i > _ref; stringOffset <= _ref ? _i++ : _i--){ _results.push(_i); }
+ return _results;
+ }).apply(this);
+ }
+ queryLength = query.length;
+ stringLength = string.length;
+ indexInQuery = 0;
+ indexInString = 0;
+ matches = [];
+ while (indexInQuery < queryLength) {
+ character = query[indexInQuery++];
+ lowerCaseIndex = string.indexOf(character.toLowerCase());
+ upperCaseIndex = string.indexOf(character.toUpperCase());
+ minIndex = Math.min(lowerCaseIndex, upperCaseIndex);
+ if (minIndex === -1) {
+ minIndex = Math.max(lowerCaseIndex, upperCaseIndex);
+ }
+ indexInString = minIndex;
+ if (indexInString === -1) {
+ return [];
+ }
+ matches.push(stringOffset + indexInString);
+ stringOffset += indexInString + 1;
+ string = string.substring(indexInString + 1, stringLength);
+ }
+ return matches;
+ };
+
+}).call(this);
+
+},{"path":7}],5:[function(require,module,exports){
+(function() {
+ var PathSeparator, scorer;
+
+ PathSeparator = require('path').sep;
+
+ scorer = require('./scorer');
+
+ exports.basenameMatch = function(subject, subject_lw, prepQuery) {
+ var basePos, depth, end;
+ end = subject.length - 1;
+ while (subject[end] === PathSeparator) {
+ end--;
+ }
+ basePos = subject.lastIndexOf(PathSeparator, end);
+ if (basePos === -1) {
+ return [];
+ }
+ depth = prepQuery.depth;
+ while (depth-- > 0) {
+ basePos = subject.lastIndexOf(PathSeparator, basePos - 1);
+ if (basePos === -1) {
+ return [];
+ }
+ }
+ basePos++;
+ end++;
+ return exports.match(subject.slice(basePos, end), subject_lw.slice(basePos, end), prepQuery, basePos);
+ };
+
+ exports.mergeMatches = function(a, b) {
+ var ai, bj, i, j, m, n, out;
+ m = a.length;
+ n = b.length;
+ if (n === 0) {
+ return a.slice();
+ }
+ if (m === 0) {
+ return b.slice();
+ }
+ i = -1;
+ j = 0;
+ bj = b[j];
+ out = [];
+ while (++i < m) {
+ ai = a[i];
+ while (bj <= ai && ++j < n) {
+ if (bj < ai) {
+ out.push(bj);
+ }
+ bj = b[j];
+ }
+ out.push(ai);
+ }
+ while (j < n) {
+ out.push(b[j++]);
+ }
+ return out;
+ };
+
+ exports.match = function(subject, subject_lw, prepQuery, offset) {
+ var DIAGONAL, LEFT, STOP, UP, acro_score, align, backtrack, csc_diag, csc_row, csc_score, i, j, m, matches, move, n, pos, query, query_lw, score, score_diag, score_row, score_up, si_lw, start, trace;
+ if (offset == null) {
+ offset = 0;
+ }
+ query = prepQuery.query;
+ query_lw = prepQuery.query_lw;
+ m = subject.length;
+ n = query.length;
+ acro_score = scorer.scoreAcronyms(subject, subject_lw, query, query_lw).score;
+ score_row = new Array(n);
+ csc_row = new Array(n);
+ STOP = 0;
+ UP = 1;
+ LEFT = 2;
+ DIAGONAL = 3;
+ trace = new Array(m * n);
+ pos = -1;
+ j = -1;
+ while (++j < n) {
+ score_row[j] = 0;
+ csc_row[j] = 0;
+ }
+ i = -1;
+ while (++i < m) {
+ score = 0;
+ score_up = 0;
+ csc_diag = 0;
+ si_lw = subject_lw[i];
+ j = -1;
+ while (++j < n) {
+ csc_score = 0;
+ align = 0;
+ score_diag = score_up;
+ if (query_lw[j] === si_lw) {
+ start = scorer.isWordStart(i, subject, subject_lw);
+ csc_score = csc_diag > 0 ? csc_diag : scorer.scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start);
+ align = score_diag + scorer.scoreCharacter(i, j, start, acro_score, csc_score);
+ }
+ score_up = score_row[j];
+ csc_diag = csc_row[j];
+ if (score > score_up) {
+ move = LEFT;
+ } else {
+ score = score_up;
+ move = UP;
+ }
+ if (align > score) {
+ score = align;
+ move = DIAGONAL;
+ } else {
+ csc_score = 0;
+ }
+ score_row[j] = score;
+ csc_row[j] = csc_score;
+ trace[++pos] = score > 0 ? move : STOP;
+ }
+ }
+ i = m - 1;
+ j = n - 1;
+ pos = i * n + j;
+ backtrack = true;
+ matches = [];
+ while (backtrack && i >= 0 && j >= 0) {
+ switch (trace[pos]) {
+ case UP:
+ i--;
+ pos -= n;
+ break;
+ case LEFT:
+ j--;
+ pos--;
+ break;
+ case DIAGONAL:
+ matches.push(i + offset);
+ j--;
+ i--;
+ pos -= n + 1;
+ break;
+ default:
+ backtrack = false;
+ }
+ }
+ matches.reverse();
+ return matches;
+ };
+
+}).call(this);
+
+},{"./scorer":6,"path":7}],6:[function(require,module,exports){
+(function() {
+ var AcronymResult, PathSeparator, Query, basenameScore, coreChars, countDir, doScore, emptyAcronymResult, file_coeff, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, opt_char_re, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_depth, tau_size, truncatedUpperCase, wm;
+
+ PathSeparator = require('path').sep;
+
+ wm = 150;
+
+ pos_bonus = 20;
+
+ tau_depth = 13;
+
+ tau_size = 85;
+
+ file_coeff = 1.2;
+
+ miss_coeff = 0.75;
+
+ opt_char_re = /[ _\-:\/\\]/g;
+
+ exports.coreChars = coreChars = function(query) {
+ return query.replace(opt_char_re, '');
+ };
+
+ exports.score = function(string, query, prepQuery, allowErrors) {
+ var score, string_lw;
+ if (prepQuery == null) {
+ prepQuery = new Query(query);
+ }
+ if (allowErrors == null) {
+ allowErrors = false;
+ }
+ if (!(allowErrors || isMatch(string, prepQuery.core_lw, prepQuery.core_up))) {
+ return 0;
+ }
+ string_lw = string.toLowerCase();
+ score = doScore(string, string_lw, prepQuery);
+ return Math.ceil(basenameScore(string, string_lw, prepQuery, score));
+ };
+
+ Query = (function() {
+ function Query(query) {
+ if (!(query != null ? query.length : void 0)) {
+ return null;
+ }
+ this.query = query;
+ this.query_lw = query.toLowerCase();
+ this.core = coreChars(query);
+ this.core_lw = this.core.toLowerCase();
+ this.core_up = truncatedUpperCase(this.core);
+ this.depth = countDir(query, query.length);
+ }
+
+ return Query;
+
+ })();
+
+ exports.prepQuery = function(query) {
+ return new Query(query);
+ };
+
+ exports.isMatch = isMatch = function(subject, query_lw, query_up) {
+ var i, j, m, n, qj_lw, qj_up, si;
+ m = subject.length;
+ n = query_lw.length;
+ if (!m || n > m) {
+ return false;
+ }
+ i = -1;
+ j = -1;
+ while (++j < n) {
+ qj_lw = query_lw[j];
+ qj_up = query_up[j];
+ while (++i < m) {
+ si = subject[i];
+ if (si === qj_lw || si === qj_up) {
+ break;
+ }
+ }
+ if (i === m) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ doScore = function(subject, subject_lw, prepQuery) {
+ var acro, acro_score, align, csc_diag, csc_row, csc_score, i, j, m, miss_budget, miss_left, mm, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz;
+ query = prepQuery.query;
+ query_lw = prepQuery.query_lw;
+ m = subject.length;
+ n = query.length;
+ acro = scoreAcronyms(subject, subject_lw, query, query_lw);
+ acro_score = acro.score;
+ if (acro.count === n) {
+ return scoreExact(n, m, acro_score, acro.pos);
+ }
+ pos = subject_lw.indexOf(query_lw);
+ if (pos > -1) {
+ return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m);
+ }
+ score_row = new Array(n);
+ csc_row = new Array(n);
+ sz = scoreSize(n, m);
+ miss_budget = Math.ceil(miss_coeff * n) + 5;
+ miss_left = miss_budget;
+ j = -1;
+ while (++j < n) {
+ score_row[j] = 0;
+ csc_row[j] = 0;
+ }
+ i = subject_lw.indexOf(query_lw[0]);
+ if (i > -1) {
+ i--;
+ }
+ mm = subject_lw.lastIndexOf(query_lw[n - 1], m);
+ if (mm > i) {
+ m = mm + 1;
+ }
+ while (++i < m) {
+ score = 0;
+ score_diag = 0;
+ csc_diag = 0;
+ si_lw = subject_lw[i];
+ record_miss = true;
+ j = -1;
+ while (++j < n) {
+ score_up = score_row[j];
+ if (score_up > score) {
+ score = score_up;
+ }
+ csc_score = 0;
+ if (query_lw[j] === si_lw) {
+ start = isWordStart(i, subject, subject_lw);
+ csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start);
+ align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score);
+ if (align > score) {
+ score = align;
+ miss_left = miss_budget;
+ } else {
+ if (record_miss && --miss_left <= 0) {
+ return score_row[n - 1] * sz;
+ }
+ record_miss = false;
+ }
+ }
+ score_diag = score_up;
+ csc_diag = csc_row[j];
+ csc_row[j] = csc_score;
+ score_row[j] = score;
+ }
+ }
+ return score * sz;
+ };
+
+ exports.isWordStart = isWordStart = function(pos, subject, subject_lw) {
+ var curr_s, prev_s;
+ if (pos === 0) {
+ return true;
+ }
+ curr_s = subject[pos];
+ prev_s = subject[pos - 1];
+ return isSeparator(curr_s) || isSeparator(prev_s) || (curr_s !== subject_lw[pos] && prev_s === subject_lw[pos - 1]);
+ };
+
+ exports.isWordEnd = isWordEnd = function(pos, subject, subject_lw, len) {
+ var curr_s, next_s;
+ if (pos === len - 1) {
+ return true;
+ }
+ curr_s = subject[pos];
+ next_s = subject[pos + 1];
+ return isSeparator(curr_s) || isSeparator(next_s) || (curr_s === subject_lw[pos] && next_s !== subject_lw[pos + 1]);
+ };
+
+ isSeparator = function(c) {
+ return c === ' ' || c === '.' || c === '-' || c === '_' || c === '/' || c === '\\';
+ };
+
+ scorePosition = function(pos) {
+ var sc;
+ if (pos < pos_bonus) {
+ sc = pos_bonus - pos;
+ return 100 + sc * sc;
+ } else {
+ return Math.max(100 + pos_bonus - pos, 0);
+ }
+ };
+
+ scoreSize = function(n, m) {
+ return tau_size / (tau_size + Math.abs(m - n));
+ };
+
+ scoreExact = function(n, m, quality, pos) {
+ return 2 * n * (wm * quality + scorePosition(pos)) * scoreSize(n, m);
+ };
+
+ exports.scorePattern = scorePattern = function(count, len, sameCase, start, end) {
+ var bonus, sz;
+ sz = count;
+ bonus = 6;
+ if (sameCase === count) {
+ bonus += 2;
+ }
+ if (start) {
+ bonus += 3;
+ }
+ if (end) {
+ bonus += 1;
+ }
+ if (count === len) {
+ if (start) {
+ if (sameCase === len) {
+ sz += 2;
+ } else {
+ sz += 1;
+ }
+ }
+ if (end) {
+ bonus += 1;
+ }
+ }
+ return sameCase + sz * (sz + bonus);
+ };
+
+ exports.scoreCharacter = scoreCharacter = function(i, j, start, acro_score, csc_score) {
+ var posBonus;
+ posBonus = scorePosition(i);
+ if (start) {
+ return posBonus + wm * ((acro_score > csc_score ? acro_score : csc_score) + 10);
+ }
+ return posBonus + wm * csc_score;
+ };
+
+ exports.scoreConsecutives = scoreConsecutives = function(subject, subject_lw, query, query_lw, i, j, start) {
+ var k, m, mi, n, nj, sameCase, startPos, sz;
+ m = subject.length;
+ n = query.length;
+ mi = m - i;
+ nj = n - j;
+ k = mi < nj ? mi : nj;
+ startPos = i;
+ sameCase = 0;
+ sz = 0;
+ if (query[j] === subject[i]) {
+ sameCase++;
+ }
+ while (++sz < k && query_lw[++j] === subject_lw[++i]) {
+ if (query[j] === subject[i]) {
+ sameCase++;
+ }
+ }
+ if (sz === 1) {
+ return 1 + 2 * sameCase;
+ }
+ return scorePattern(sz, n, sameCase, start, isWordEnd(i, subject, subject_lw, m));
+ };
+
+ exports.scoreExactMatch = scoreExactMatch = function(subject, subject_lw, query, query_lw, pos, n, m) {
+ var end, i, pos2, sameCase, start;
+ start = isWordStart(pos, subject, subject_lw);
+ if (!start) {
+ pos2 = subject_lw.indexOf(query_lw, pos + 1);
+ if (pos2 > -1) {
+ start = isWordStart(pos2, subject, subject_lw);
+ if (start) {
+ pos = pos2;
+ }
+ }
+ }
+ i = -1;
+ sameCase = 0;
+ while (++i < n) {
+ if (query[pos + i] === subject[i]) {
+ sameCase++;
+ }
+ }
+ end = isWordEnd(pos + n - 1, subject, subject_lw, m);
+ return scoreExact(n, m, scorePattern(n, n, sameCase, start, end), pos);
+ };
+
+ AcronymResult = (function() {
+ function AcronymResult(score, pos, count) {
+ this.score = score;
+ this.pos = pos;
+ this.count = count;
+ }
+
+ return AcronymResult;
+
+ })();
+
+ emptyAcronymResult = new AcronymResult(0, 0.1, 0);
+
+ exports.scoreAcronyms = scoreAcronyms = function(subject, subject_lw, query, query_lw) {
+ var count, i, j, m, n, pos, qj_lw, sameCase, score;
+ m = subject.length;
+ n = query.length;
+ if (!(m > 1 && n > 1)) {
+ return emptyAcronymResult;
+ }
+ count = 0;
+ pos = 0;
+ sameCase = 0;
+ i = -1;
+ j = -1;
+ while (++j < n) {
+ qj_lw = query_lw[j];
+ while (++i < m) {
+ if (qj_lw === subject_lw[i] && isWordStart(i, subject, subject_lw)) {
+ if (query[j] === subject[i]) {
+ sameCase++;
+ }
+ pos += i;
+ count++;
+ break;
+ }
+ }
+ if (i === m) {
+ break;
+ }
+ }
+ if (count < 2) {
+ return emptyAcronymResult;
+ }
+ score = scorePattern(count, n, sameCase, true, false);
+ return new AcronymResult(score, pos / count, count);
+ };
+
+ basenameScore = function(subject, subject_lw, prepQuery, fullPathScore) {
+ var alpha, basePathScore, basePos, depth, end;
+ if (fullPathScore === 0) {
+ return 0;
+ }
+ end = subject.length - 1;
+ while (subject[end] === PathSeparator) {
+ end--;
+ }
+ basePos = subject.lastIndexOf(PathSeparator, end);
+ if (basePos === -1) {
+ return fullPathScore;
+ }
+ depth = prepQuery.depth;
+ while (depth-- > 0) {
+ basePos = subject.lastIndexOf(PathSeparator, basePos - 1);
+ if (basePos === -1) {
+ return fullPathScore;
+ }
+ }
+ basePos++;
+ end++;
+ basePathScore = doScore(subject.slice(basePos, end), subject_lw.slice(basePos, end), prepQuery);
+ alpha = 0.5 * tau_depth / (tau_depth + countDir(subject, end + 1));
+ return alpha * basePathScore + (1 - alpha) * fullPathScore * scoreSize(0, file_coeff * (end - basePos));
+ };
+
+ exports.countDir = countDir = function(path, end) {
+ var count, i;
+ if (end < 1) {
+ return 0;
+ }
+ count = 0;
+ i = -1;
+ while (++i < end && path[i] === PathSeparator) {
+ continue;
+ }
+ while (++i < end) {
+ if (path[i] === PathSeparator) {
+ count++;
+ while (++i < end && path[i] === PathSeparator) {
+ continue;
+ }
+ }
+ }
+ return count;
+ };
+
+ truncatedUpperCase = function(str) {
+ var char, upper, _i, _len;
+ upper = "";
+ for (_i = 0, _len = str.length; _i < _len; _i++) {
+ char = str[_i];
+ upper += char.toUpperCase()[0];
+ }
+ return upper;
+ };
+
+}).call(this);
+
+},{"path":7}],7:[function(require,module,exports){
+(function (process){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// resolves . and .. elements in a path array with directory names there
+// must be no slashes, empty elements, or device names (c:\) in the array
+// (so also no leading and trailing slashes - it does not distinguish
+// relative and absolute paths)
+function normalizeArray(parts, allowAboveRoot) {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === '.') {
+ parts.splice(i, 1);
+ } else if (last === '..') {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (; up--; up) {
+ parts.unshift('..');
+ }
+ }
+
+ return parts;
+}
+
+// Split a filename into [root, dir, basename, ext], unix version
+// 'root' is just a slash, or nothing.
+var splitPathRe =
+ /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+var splitPath = function(filename) {
+ return splitPathRe.exec(filename).slice(1);
+};
+
+// path.resolve([from ...], to)
+// posix version
+exports.resolve = function() {
+ var resolvedPath = '',
+ resolvedAbsolute = false;
+
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? arguments[i] : process.cwd();
+
+ // Skip empty and invalid entries
+ if (typeof path !== 'string') {
+ throw new TypeError('Arguments to path.resolve must be strings');
+ } else if (!path) {
+ continue;
+ }
+
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charAt(0) === '/';
+ }
+
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+
+ // Normalize the path
+ resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
+ return !!p;
+ }), !resolvedAbsolute).join('/');
+
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+};
+
+// path.normalize(path)
+// posix version
+exports.normalize = function(path) {
+ var isAbsolute = exports.isAbsolute(path),
+ trailingSlash = substr(path, -1) === '/';
+
+ // Normalize the path
+ path = normalizeArray(filter(path.split('/'), function(p) {
+ return !!p;
+ }), !isAbsolute).join('/');
+
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+
+ return (isAbsolute ? '/' : '') + path;
+};
+
+// posix version
+exports.isAbsolute = function(path) {
+ return path.charAt(0) === '/';
+};
+
+// posix version
+exports.join = function() {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return exports.normalize(filter(paths, function(p, index) {
+ if (typeof p !== 'string') {
+ throw new TypeError('Arguments to path.join must be strings');
+ }
+ return p;
+ }).join('/'));
+};
+
+
+// path.relative(from, to)
+// posix version
+exports.relative = function(from, to) {
+ from = exports.resolve(from).substr(1);
+ to = exports.resolve(to).substr(1);
+
+ function trim(arr) {
+ var start = 0;
+ for (; start < arr.length; start++) {
+ if (arr[start] !== '') break;
+ }
+
+ var end = arr.length - 1;
+ for (; end >= 0; end--) {
+ if (arr[end] !== '') break;
+ }
+
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+
+ var fromParts = trim(from.split('/'));
+ var toParts = trim(to.split('/'));
+
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push('..');
+ }
+
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+
+ return outputParts.join('/');
+};
+
+exports.sep = '/';
+exports.delimiter = ':';
+
+exports.dirname = function(path) {
+ var result = splitPath(path),
+ root = result[0],
+ dir = result[1];
+
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return '.';
+ }
+
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.substr(0, dir.length - 1);
+ }
+
+ return root + dir;
+};
+
+
+exports.basename = function(path, ext) {
+ var f = splitPath(path)[2];
+ // TODO: make this comparison case-insensitive on windows?
+ if (ext && f.substr(-1 * ext.length) === ext) {
+ f = f.substr(0, f.length - ext.length);
+ }
+ return f;
+};
+
+
+exports.extname = function(path) {
+ return splitPath(path)[3];
+};
+
+function filter (xs, f) {
+ if (xs.filter) return xs.filter(f);
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ if (f(xs[i], i, xs)) res.push(xs[i]);
+ }
+ return res;
+}
+
+// String.prototype.substr - negative index don't work in IE8
+var substr = 'ab'.substr(-1) === 'b'
+ ? function (str, start, len) { return str.substr(start, len) }
+ : function (str, start, len) {
+ if (start < 0) start = str.length + start;
+ return str.substr(start, len);
+ }
+;
+
+}).call(this,require('_process'))
+},{"_process":8}],8:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = setTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ clearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ setTimeout(drainQueue, 0);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}]},{},[1]);
diff --git a/vendor/assets/javascripts/fuzzaldrin-plus.min.js b/vendor/assets/javascripts/fuzzaldrin-plus.min.js
deleted file mode 100644
index 3f25c2d8373..00000000000
--- a/vendor/assets/javascripts/fuzzaldrin-plus.min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){(function(){var PathSeparator,legacy_scorer,pluckCandidates,scorer,sortCandidates;scorer=require('./scorer');legacy_scorer=require('./legacy');pluckCandidates=function(a){return a.candidate};sortCandidates=function(a,b){return b.score-a.score};PathSeparator=require('path').sep;module.exports=function(candidates,query,arg){var allowErrors,bAllowErrors,bKey,candidate,coreQuery,i,j,key,legacy,len,len1,maxInners,maxResults,prepQuery,queryHasSlashes,ref,score,scoredCandidates,spotLeft,string;ref=arg!=null?arg:{},key=ref.key,maxResults=ref.maxResults,maxInners=ref.maxInners,allowErrors=ref.allowErrors,legacy=ref.legacy;scoredCandidates=[];spotLeft=(maxInners!=null)&&maxInners>0?maxInners:candidates.length;bAllowErrors=!!allowErrors;bKey=key!=null;prepQuery=scorer.prepQuery(query);if(!legacy){for(i=0,len=candidates.length;i<len;i++){candidate=candidates[i];string=bKey?candidate[key]:candidate;if(!string){continue}score=scorer.score(string,query,prepQuery,bAllowErrors);if(score>0){scoredCandidates.push({candidate:candidate,score:score});if(!--spotLeft){break}}}}else{queryHasSlashes=prepQuery.depth>0;coreQuery=prepQuery.core;for(j=0,len1=candidates.length;j<len1;j++){candidate=candidates[j];string=key!=null?candidate[key]:candidate;if(!string){continue}score=legacy_scorer.score(string,coreQuery,queryHasSlashes);if(!queryHasSlashes){score=legacy_scorer.basenameScore(string,coreQuery,score)}if(score>0){scoredCandidates.push({candidate:candidate,score:score})}}}scoredCandidates.sort(sortCandidates);candidates=scoredCandidates.map(pluckCandidates);if(maxResults!=null){candidates=candidates.slice(0,maxResults)}return candidates}}).call(this)},{"./legacy":4,"./scorer":6,"path":7}],2:[function(require,module,exports){(function(){var PathSeparator,filter,legacy_scorer,matcher,prepQueryCache,scorer;scorer=require('./scorer');legacy_scorer=require('./legacy');filter=require('./filter');matcher=require('./matcher');PathSeparator=require('path').sep;prepQueryCache=null;module.exports={filter:function(candidates,query,options){if(!((query!=null?query.length:void 0)&&(candidates!=null?candidates.length:void 0))){return[]}return filter(candidates,query,options)},prepQuery:function(query){return scorer.prepQuery(query)},score:function(string,query,prepQuery,arg){var allowErrors,coreQuery,legacy,queryHasSlashes,ref,score;ref=arg!=null?arg:{},allowErrors=ref.allowErrors,legacy=ref.legacy;if(!((string!=null?string.length:void 0)&&(query!=null?query.length:void 0))){return 0}if(prepQuery==null){prepQuery=prepQueryCache&&prepQueryCache.query===query?prepQueryCache:(prepQueryCache=scorer.prepQuery(query))}if(!legacy){score=scorer.score(string,query,prepQuery,!!allowErrors)}else{queryHasSlashes=prepQuery.depth>0;coreQuery=prepQuery.core;score=legacy_scorer.score(string,coreQuery,queryHasSlashes);if(!queryHasSlashes){score=legacy_scorer.basenameScore(string,coreQuery,score)}}return score},match:function(string,query,prepQuery,arg){var allowErrors,baseMatches,i,matches,query_lw,ref,results,string_lw;allowErrors=(arg!=null?arg:{}).allowErrors;if(!string){return[]}if(!query){return[]}if(string===query){return(function(){results=[];for(var i=0,ref=string.length;0<=ref?i<ref:i>ref;0<=ref?i++:i--){results.push(i)}return results}).apply(this)}if(prepQuery==null){prepQuery=prepQueryCache&&prepQueryCache.query===query?prepQueryCache:(prepQueryCache=scorer.prepQuery(query))}if(!(allowErrors||scorer.isMatch(string,prepQuery.core_lw,prepQuery.core_up))){return[]}string_lw=string.toLowerCase();query_lw=prepQuery.query_lw;matches=matcher.match(string,string_lw,prepQuery);if(matches.length===0){return matches}if(string.indexOf(PathSeparator)>-1){baseMatches=matcher.basenameMatch(string,string_lw,prepQuery);matches=matcher.mergeMatches(matches,baseMatches)}return matches}}}).call(this)},{"./filter":1,"./legacy":4,"./matcher":5,"./scorer":6,"path":7}],3:[function(require,module,exports){fuzzaldrinPlus=require('./fuzzaldrin')},{"./fuzzaldrin":2}],4:[function(require,module,exports){(function(){var PathSeparator,queryIsLastPathSegment;PathSeparator=require('path').sep;exports.basenameScore=function(string,query,score){var base,depth,index,lastCharacter,segmentCount,slashCount;index=string.length-1;while(string[index]===PathSeparator){index--}slashCount=0;lastCharacter=index;base=null;while(index>=0){if(string[index]===PathSeparator){slashCount++;if(base==null){base=string.substring(index+1,lastCharacter+1)}}else if(index===0){if(lastCharacter<string.length-1){if(base==null){base=string.substring(0,lastCharacter+1)}}else{if(base==null){base=string}}}index--}if(base===string){score*=2}else if(base){score+=exports.score(base,query)}segmentCount=slashCount+1;depth=Math.max(1,10-segmentCount);score*=depth*0.01;return score};exports.score=function(string,query){var character,characterScore,indexInQuery,indexInString,lowerCaseIndex,minIndex,queryLength,queryScore,ref,stringLength,totalCharacterScore,upperCaseIndex;if(string===query){return 1}if(queryIsLastPathSegment(string,query)){return 1}totalCharacterScore=0;queryLength=query.length;stringLength=string.length;indexInQuery=0;indexInString=0;while(indexInQuery<queryLength){character=query[indexInQuery++];lowerCaseIndex=string.indexOf(character.toLowerCase());upperCaseIndex=string.indexOf(character.toUpperCase());minIndex=Math.min(lowerCaseIndex,upperCaseIndex);if(minIndex===-1){minIndex=Math.max(lowerCaseIndex,upperCaseIndex)}indexInString=minIndex;if(indexInString===-1){return 0}characterScore=0.1;if(string[indexInString]===character){characterScore+=0.1}if(indexInString===0||string[indexInString-1]===PathSeparator){characterScore+=0.8}else if((ref=string[indexInString-1])==='-'||ref==='_'||ref===' '){characterScore+=0.7}string=string.substring(indexInString+1,stringLength);totalCharacterScore+=characterScore}queryScore=totalCharacterScore/queryLength;return((queryScore*(queryLength/stringLength))+queryScore)/2};queryIsLastPathSegment=function(string,query){if(string[string.length-query.length-1]===PathSeparator){return string.lastIndexOf(query)===string.length-query.length}};exports.match=function(string,query,stringOffset){var character,i,indexInQuery,indexInString,lowerCaseIndex,matches,minIndex,queryLength,ref,results,stringLength,upperCaseIndex;if(stringOffset==null){stringOffset=0}if(string===query){return(function(){results=[];for(var i=stringOffset,ref=stringOffset+string.length;stringOffset<=ref?i<ref:i>ref;stringOffset<=ref?i++:i--){results.push(i)}return results}).apply(this)}queryLength=query.length;stringLength=string.length;indexInQuery=0;indexInString=0;matches=[];while(indexInQuery<queryLength){character=query[indexInQuery++];lowerCaseIndex=string.indexOf(character.toLowerCase());upperCaseIndex=string.indexOf(character.toUpperCase());minIndex=Math.min(lowerCaseIndex,upperCaseIndex);if(minIndex===-1){minIndex=Math.max(lowerCaseIndex,upperCaseIndex)}indexInString=minIndex;if(indexInString===-1){return[]}matches.push(stringOffset+indexInString);stringOffset+=indexInString+1;string=string.substring(indexInString+1,stringLength)}return matches}}).call(this)},{"path":7}],5:[function(require,module,exports){(function(){var PathSeparator,scorer;PathSeparator=require('path').sep;scorer=require('./scorer');exports.basenameMatch=function(subject,subject_lw,prepQuery){var basePos,depth,end;end=subject.length-1;while(subject[end]===PathSeparator){end--}basePos=subject.lastIndexOf(PathSeparator,end);if(basePos===-1){return[]}depth=prepQuery.depth;while(depth-->0){basePos=subject.lastIndexOf(PathSeparator,basePos-1);if(basePos===-1){return[]}}basePos++;end++;return exports.match(subject.slice(basePos,end),subject_lw.slice(basePos,end),prepQuery,basePos)};exports.mergeMatches=function(a,b){var ai,bj,i,j,m,n,out;m=a.length;n=b.length;if(n===0){return a.slice()}if(m===0){return b.slice()}i=-1;j=0;bj=b[j];out=[];while(++i<m){ai=a[i];while(bj<=ai&&++j<n){if(bj<ai){out.push(bj)}bj=b[j]}out.push(ai)}while(j<n){out.push(b[j++])}return out};exports.match=function(subject,subject_lw,prepQuery,offset){var DIAGONAL,LEFT,STOP,UP,acro_score,align,backtrack,csc_diag,csc_row,csc_score,i,j,m,matches,move,n,pos,query,query_lw,score,score_diag,score_row,score_up,si_lw,start,trace;if(offset==null){offset=0}query=prepQuery.query;query_lw=prepQuery.query_lw;m=subject.length;n=query.length;acro_score=scorer.scoreAcronyms(subject,subject_lw,query,query_lw).score;score_row=new Array(n);csc_row=new Array(n);STOP=0;UP=1;LEFT=2;DIAGONAL=3;trace=new Array(m*n);pos=-1;j=-1;while(++j<n){score_row[j]=0;csc_row[j]=0}i=-1;while(++i<m){score=0;score_up=0;csc_diag=0;si_lw=subject_lw[i];j=-1;while(++j<n){csc_score=0;align=0;score_diag=score_up;if(query_lw[j]===si_lw){start=scorer.isWordStart(i,subject,subject_lw);csc_score=csc_diag>0?csc_diag:scorer.scoreConsecutives(subject,subject_lw,query,query_lw,i,j,start);align=score_diag+scorer.scoreCharacter(i,j,start,acro_score,csc_score)}score_up=score_row[j];csc_diag=csc_row[j];if(score>score_up){move=LEFT}else{score=score_up;move=UP}if(align>score){score=align;move=DIAGONAL}else{csc_score=0}score_row[j]=score;csc_row[j]=csc_score;trace[++pos]=score>0?move:STOP}}i=m-1;j=n-1;pos=i*n+j;backtrack=true;matches=[];while(backtrack&&i>=0&&j>=0){switch(trace[pos]){case UP:i--;pos-=n;break;case LEFT:j--;pos--;break;case DIAGONAL:matches.push(i+offset);j--;i--;pos-=n+1;break;default:backtrack=false}}matches.reverse();return matches}}).call(this)},{"./scorer":6,"path":7}],6:[function(require,module,exports){(function(){var AcronymResult,PathSeparator,Query,basenameScore,coreChars,countDir,doScore,emptyAcronymResult,file_coeff,isMatch,isSeparator,isWordEnd,isWordStart,miss_coeff,opt_char_re,pos_bonus,scoreAcronyms,scoreCharacter,scoreConsecutives,scoreExact,scoreExactMatch,scorePattern,scorePosition,scoreSize,tau_depth,tau_size,truncatedUpperCase,wm;PathSeparator=require('path').sep;wm=150;pos_bonus=20;tau_depth=13;tau_size=85;file_coeff=1.2;miss_coeff=0.75;opt_char_re=/[ _\-:\/\\]/g;exports.coreChars=coreChars=function(query){return query.replace(opt_char_re,'')};exports.score=function(string,query,prepQuery,allowErrors){var score,string_lw;if(prepQuery==null){prepQuery=new Query(query)}if(allowErrors==null){allowErrors=false}if(!(allowErrors||isMatch(string,prepQuery.core_lw,prepQuery.core_up))){return 0}string_lw=string.toLowerCase();score=doScore(string,string_lw,prepQuery);return Math.ceil(basenameScore(string,string_lw,prepQuery,score))};Query=(function(){function Query(query){if(!(query!=null?query.length:void 0)){return null}this.query=query;this.query_lw=query.toLowerCase();this.core=coreChars(query);this.core_lw=this.core.toLowerCase();this.core_up=truncatedUpperCase(this.core);this.depth=countDir(query,query.length)}return Query})();exports.prepQuery=function(query){return new Query(query)};exports.isMatch=isMatch=function(subject,query_lw,query_up){var i,j,m,n,qj_lw,qj_up,si;m=subject.length;n=query_lw.length;if(!m||!n||n>m){return false}i=-1;j=-1;while(++j<n){qj_lw=query_lw[j];qj_up=query_up[j];while(++i<m){si=subject[i];if(si===qj_lw||si===qj_up){break}}if(i===m){return false}}return true};doScore=function(subject,subject_lw,prepQuery){var acro,acro_score,align,csc_diag,csc_row,csc_score,i,j,m,miss_budget,miss_left,mm,n,pos,query,query_lw,record_miss,score,score_diag,score_row,score_up,si_lw,start,sz;query=prepQuery.query;query_lw=prepQuery.query_lw;m=subject.length;n=query.length;acro=scoreAcronyms(subject,subject_lw,query,query_lw);acro_score=acro.score;if(acro.count===n){return scoreExact(n,m,acro_score,acro.pos)}pos=subject_lw.indexOf(query_lw);if(pos>-1){return scoreExactMatch(subject,subject_lw,query,query_lw,pos,n,m)}score_row=new Array(n);csc_row=new Array(n);sz=scoreSize(n,m);miss_budget=Math.ceil(miss_coeff*n)+5;miss_left=miss_budget;j=-1;while(++j<n){score_row[j]=0;csc_row[j]=0}i=subject_lw.indexOf(query_lw[0]);if(i>-1){i--}mm=subject_lw.lastIndexOf(query_lw[n-1],m);if(mm>i){m=mm+1}while(++i<m){score=0;score_diag=0;csc_diag=0;si_lw=subject_lw[i];record_miss=true;j=-1;while(++j<n){score_up=score_row[j];if(score_up>score){score=score_up}csc_score=0;if(query_lw[j]===si_lw){start=isWordStart(i,subject,subject_lw);csc_score=csc_diag>0?csc_diag:scoreConsecutives(subject,subject_lw,query,query_lw,i,j,start);align=score_diag+scoreCharacter(i,j,start,acro_score,csc_score);if(align>score){score=align;miss_left=miss_budget}else{if(record_miss&&--miss_left<=0){return score_row[n-1]*sz}record_miss=false}}score_diag=score_up;csc_diag=csc_row[j];csc_row[j]=csc_score;score_row[j]=score}}return score*sz};exports.isWordStart=isWordStart=function(pos,subject,subject_lw){var curr_s,prev_s;if(pos===0){return true}curr_s=subject[pos];prev_s=subject[pos-1];return isSeparator(curr_s)||isSeparator(prev_s)||(curr_s!==subject_lw[pos]&&prev_s===subject_lw[pos-1])};exports.isWordEnd=isWordEnd=function(pos,subject,subject_lw,len){var curr_s,next_s;if(pos===len-1){return true}curr_s=subject[pos];next_s=subject[pos+1];return isSeparator(curr_s)||isSeparator(next_s)||(curr_s===subject_lw[pos]&&next_s!==subject_lw[pos+1])};isSeparator=function(c){return c===' '||c==='.'||c==='-'||c==='_'||c==='/'||c==='\\'};scorePosition=function(pos){var sc;if(pos<pos_bonus){sc=pos_bonus-pos;return 100+sc*sc}else{return Math.max(100+pos_bonus-pos,0)}};scoreSize=function(n,m){return tau_size/(tau_size+Math.abs(m-n))};scoreExact=function(n,m,quality,pos){return 2*n*(wm*quality+scorePosition(pos))*scoreSize(n,m)};exports.scorePattern=scorePattern=function(count,len,sameCase,start,end){var bonus,sz;sz=count;bonus=6;if(sameCase===count){bonus+=2}if(start){bonus+=3}if(end){bonus+=1}if(count===len){if(start){if(sameCase===len){sz+=2}else{sz+=1}}if(end){bonus+=1}}return sameCase+sz*(sz+bonus)};exports.scoreCharacter=scoreCharacter=function(i,j,start,acro_score,csc_score){var posBonus;posBonus=scorePosition(i);if(start){return posBonus+wm*((acro_score>csc_score?acro_score:csc_score)+10)}return posBonus+wm*csc_score};exports.scoreConsecutives=scoreConsecutives=function(subject,subject_lw,query,query_lw,i,j,start){var k,m,mi,n,nj,sameCase,startPos,sz;m=subject.length;n=query.length;mi=m-i;nj=n-j;k=mi<nj?mi:nj;startPos=i;sameCase=0;sz=0;if(query[j]===subject[i]){sameCase++}while(++sz<k&&query_lw[++j]===subject_lw[++i]){if(query[j]===subject[i]){sameCase++}}if(sz===1){return 1+2*sameCase}return scorePattern(sz,n,sameCase,start,isWordEnd(i,subject,subject_lw,m))};exports.scoreExactMatch=scoreExactMatch=function(subject,subject_lw,query,query_lw,pos,n,m){var end,i,pos2,sameCase,start;start=isWordStart(pos,subject,subject_lw);if(!start){pos2=subject_lw.indexOf(query_lw,pos+1);if(pos2>-1){start=isWordStart(pos2,subject,subject_lw);if(start){pos=pos2}}}i=-1;sameCase=0;while(++i<n){if(query[pos+i]===subject[i]){sameCase++}}end=isWordEnd(pos+n-1,subject,subject_lw,m);return scoreExact(n,m,scorePattern(n,n,sameCase,start,end),pos)};AcronymResult=(function(){function AcronymResult(score1,pos1,count1){this.score=score1;this.pos=pos1;this.count=count1}return AcronymResult})();emptyAcronymResult=new AcronymResult(0,0.1,0);exports.scoreAcronyms=scoreAcronyms=function(subject,subject_lw,query,query_lw){var count,i,j,m,n,pos,qj_lw,sameCase,score;m=subject.length;n=query.length;if(!(m>1&&n>1)){return emptyAcronymResult}count=0;pos=0;sameCase=0;i=-1;j=-1;while(++j<n){qj_lw=query_lw[j];while(++i<m){if(qj_lw===subject_lw[i]&&isWordStart(i,subject,subject_lw)){if(query[j]===subject[i]){sameCase++}pos+=i;count++;break}}if(i===m){break}}if(count<2){return emptyAcronymResult}score=scorePattern(count,n,sameCase,true,false);return new AcronymResult(score,pos/count,count)};basenameScore=function(subject,subject_lw,prepQuery,fullPathScore){var alpha,basePathScore,basePos,depth,end;if(fullPathScore===0){return 0}end=subject.length-1;while(subject[end]===PathSeparator){end--}basePos=subject.lastIndexOf(PathSeparator,end);if(basePos===-1){return fullPathScore}depth=prepQuery.depth;while(depth-->0){basePos=subject.lastIndexOf(PathSeparator,basePos-1);if(basePos===-1){return fullPathScore}}basePos++;end++;basePathScore=doScore(subject.slice(basePos,end),subject_lw.slice(basePos,end),prepQuery);alpha=0.5*tau_depth/(tau_depth+countDir(subject,end+1));return alpha*basePathScore+(1-alpha)*fullPathScore*scoreSize(0,file_coeff*(end-basePos))};exports.countDir=countDir=function(path,end){var count,i;if(end<1){return 0}count=0;i=-1;while(++i<end&&path[i]===PathSeparator){continue}while(++i<end){if(path[i]===PathSeparator){count++;while(++i<end&&path[i]===PathSeparator){continue}}}return count};truncatedUpperCase=function(str){var char,l,len1,upper;upper="";for(l=0,len1=str.length;l<len1;l++){char=str[l];upper+=char.toUpperCase()[0]}return upper}}).call(this)},{"path":7}],7:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==='.'){parts.splice(i,1)}else if(last==='..'){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift('..')}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath='',resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=(i>=0)?arguments[i]:process.cwd();if(typeof path!=='string'){throw new TypeError('Arguments to path.resolve must be strings');}else if(!path){continue}resolvedPath=path+'/'+resolvedPath;resolvedAbsolute=path.charAt(0)==='/'}resolvedPath=normalizeArray(filter(resolvedPath.split('/'),function(p){return!!p}),!resolvedAbsolute).join('/');return((resolvedAbsolute?'/':'')+resolvedPath)||'.'};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==='/';path=normalizeArray(filter(path.split('/'),function(p){return!!p}),!isAbsolute).join('/');if(!path&&!isAbsolute){path='.'}if(path&&trailingSlash){path+='/'}return(isAbsolute?'/':'')+path};exports.isAbsolute=function(path){return path.charAt(0)==='/'};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=='string'){throw new TypeError('Arguments to path.join must be strings');}return p}).join('/'))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=='')break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=='')break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split('/'));var toParts=trim(to.split('/'));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push('..')}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join('/')};exports.sep='/';exports.delimiter=':';exports.dirname=function(path){var result=splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return'.'}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir};exports.basename=function(path,ext){var f=splitPath(path)[2];if(ext&&f.substr(-1*ext.length)===ext){f=f.substr(0,f.length-ext.length)}return f};exports.extname=function(path){return splitPath(path)[3]};function filter(xs,f){if(xs.filter)return xs.filter(f);var res=[];for(var i=0;i<xs.length;i++){if(f(xs[i],i,xs))res.push(xs[i])}return res}var substr='ab'.substr(-1)==='b'?function(str,start,len){return str.substr(start,len)}:function(str,start,len){if(start<0)start=str.length+start;return str.substr(start,len)}}).call(this,require('_process'))},{"_process":8}],8:[function(require,module,exports){var process=module.exports={};var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){draining=false;if(currentQueue.length){queue=currentQueue.concat(queue)}else{queueIndex=-1}if(queue.length){drainQueue()}}function drainQueue(){if(draining){return}var timeout=setTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){if(currentQueue){currentQueue[queueIndex].run()}}queueIndex=-1;len=queue.length}currentQueue=null;draining=false;clearTimeout(timeout)}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i]}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){setTimeout(drainQueue,0)}};function Item(fun,array){this.fun=fun;this.array=array}Item.prototype.run=function(){this.fun.apply(null,this.array)};process.title='browser';process.browser=true;process.env={};process.argv=[];process.version='';process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error('process.binding is not supported');};process.cwd=function(){return'/'};process.chdir=function(dir){throw new Error('process.chdir is not supported');};process.umask=function(){return 0}},{}]},{},[3]);
diff --git a/vendor/assets/javascripts/g.bar-min.js b/vendor/assets/javascripts/g.bar-min.js
deleted file mode 100644
index 7620dabda74..00000000000
--- a/vendor/assets/javascripts/g.bar-min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*!
- * g.Raphael 0.5 - Charting library, based on Raphaël
- *
- * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
- * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
- * From: https://github.com/jhurt/g.raphael/blob/master/g.bar.js
- */
-(function(){function c(c,d,e,f,g,h,i,j){var k,l={round:"round",sharp:"sharp",soft:"soft",square:"square"};if(g&&!f||!g&&!e)return i?"":j.path();switch(h=l[h]||"square",f=Math.round(f),e=Math.round(e),c=Math.round(c),d=Math.round(d),h){case"round":if(g)m=~~(e/2),m>f?(m=f,k=["M",c-~~(e/2),d,"l",0,0,"a",~~(e/2),m,0,0,1,e,0,"l",0,0,"z"]):k=["M",c-m,d,"l",0,m-f,"a",m,m,0,1,1,e,0,"l",0,f-m,"z"];else{var m=~~(f/2);m>e?(m=e,k=["M",c+.5,d+.5-~~(f/2),"l",0,0,"a",m,~~(f/2),0,0,1,0,f,"l",0,0,"z"]):k=["M",c+.5,d+.5-m,"l",e-m,0,"a",m,m,0,1,1,0,f,"l",m-e,0,"z"]}break;case"sharp":if(g)n=~~(e/2),k=["M",c+n,d,"l",-e,0,0,-b(f-n,0),n,-a(n,f),n,a(n,f),n,"z"];else{var n=~~(f/2);k=["M",c,d+n,"l",0,-f,b(e-n,0),0,a(n,e),n,-a(n,e),n+(f>2*n),"z"]}break;case"square":k=g?["M",c+~~(e/2),d,"l",1-e,0,0,-f,e-1,0,"z"]:["M",c,d+~~(f/2),"l",0,-f,e,0,0,f,"z"];break;case"soft":g?(m=a(Math.round(e/5),f),k=["M",c-~~(e/2),d,"l",0,m-f,"a",m,m,0,0,1,m,-m,"l",e-2*m,0,"a",m,m,0,0,1,m,m,"l",0,f-m,"z"]):(m=a(e,Math.round(f/5)),k=["M",c+.5,d+.5-~~(f/2),"l",e-m,0,"a",m,m,0,0,1,m,m,"l",0,f-2*m,"a",m,m,0,0,1,-m,m,"l",m-e,0,"z"])}return i?k.join(","):j.path(k)}function d(a,b,d,e,f,g,h){h=h||{};var i=this,j=h.type||"square",k=parseFloat(h.gutter||"20%"),l=a.set(),m=a.set(),n=a.set(),o=a.set(),p=Math.max.apply(Math,g),q=[],r=0,s=h.colors||i.colors,t=g.length;if(Raphael.is(g[0],"array")){p=[],r=t,t=0;for(var u=g.length;u--;)m.push(a.set()),p.push(Math.max.apply(Math,g[u])),t=Math.max(t,g[u].length);if(h.stacked)for(var u=t;u--;){for(var v=0,w=g.length;w--;)v+=+g[w][u]||0;q.push(v)}for(var u=g.length;u--;)if(t>g[u].length)for(var w=t;w--;)g[u].push(0);p=Math.max.apply(Math,h.stacked?q:p)}p=h.to||p;var x=100*(e/(t*(100+k)+k)),y=x*k/100,z=null==h.vgutter?20:h.vgutter,A=[],B=b+y,C=(f-2*z)/p;h.stretch||(y=Math.round(y),x=Math.floor(x)),!h.stacked&&(x/=r||1);for(var u=0;t>u;u++){A=[];for(var w=0;(r||1)>w;w++){var D=Math.round((r?g[w][u]:g[u])*C),E=d+f-z-D,F=c(Math.round(B+x/2),E+D,x,D,!0,j,null,a).attr({stroke:"none",fill:s[r?w:u]});r?m[w].push(F):m.push(F),F.y=E,F.x=Math.round(B+x/2),F.w=x,F.h=D,F.value=r?g[w][u]:g[u],h.stacked?A.push(F):B+=x}if(h.stacked){var G;o.push(G=a.rect(A[0].x-A[0].w/2,d,x,f).attr(i.shim)),G.bars=a.set();for(var H=0,I=A.length;I--;)A[I].toFront();for(var I=0,J=A.length;J>I;I++){var K,F=A[I],D=(H+F.value)*C,L=c(F.x,d+f-z-.5*!!H,x,D,!0,j,1,a);G.bars.push(F),H&&F.attr({path:L}),F.h=D,F.y=d+f-z-.5*!!H-D,n.push(K=a.rect(F.x-F.w/2,F.y,x,F.value*C).attr(i.shim)),K.bar=F,K.value=F.value,H+=F.value}B+=x}B+=y}if(o.toFront(),B=b+y,!h.stacked)for(var u=0;t>u;u++){for(var w=0;(r||1)>w;w++){var K;n.push(K=a.rect(Math.round(B),d+z,x,f-z).attr(i.shim)),K.bar=r?m[w][u]:m[u],K.value=K.bar.value,B+=x}B+=y}return l.label=function(b,c){b=b||[],this.labels=a.set();var e,j=-1/0;if(h.stacked){for(var k=0;t>k;k++)for(var l=0,o=0;(r||1)>o;o++)if(l+=r?g[o][k]:g[k],o==r-1){var q=i.labelise(b[k],l,p);e=a.text(m[o][k].x,d+f-z/2,q).attr(i.txtattr).attr({fill:h.legendcolor||"#000","text-anchor":"start"}).insertBefore(n[k*(r||1)+o]);var s=e.getBBox();j>s.x-7?e.remove():(this.labels.push(e),j=s.x+s.width)}}else for(var k=0;t>k;k++)for(var o=0;(r||1)>o;o++){var q=i.labelise(r?b[o]&&b[o][k]:b[k],r?g[o][k]:g[k],p);e=a.text(m[o][k].x-x/2,c?d+f-z/2:m[o][k].y-10,q).attr(i.txtattr).attr({fill:h.legendcolor||"#000","text-anchor":"start"}).insertBefore(n[k*(r||1)+o]);var s=e.getBBox();e.translate((x-s.width)/2,1),j>s.x-7?e.remove():(this.labels.push(e),j=s.x+s.width)}return this},l.hover=function(a,b){return o.hide(),n.show(),n.mouseover(a).mouseout(b),this},l.hoverColumn=function(a,b){return n.hide(),o.show(),b=b||function(){},o.mouseover(a).mouseout(b),this},l.click=function(a){return o.hide(),n.show(),n.click(a),this},l.each=function(a){if(!Raphael.is(a,"function"))return this;for(var b=n.length;b--;)a.call(n[b]);return this},l.eachColumn=function(a){if(!Raphael.is(a,"function"))return this;for(var b=o.length;b--;)a.call(o[b]);return this},l.clickColumn=function(a){return n.hide(),o.show(),o.click(a),this},l.push(m,n,o),l.bars=m,l.covers=n,l}function e(a,b,d,e,f,g,h){h=h||{};var i=this,j=h.type||"square",k=parseFloat(h.gutter||"20%"),l=a.set(),m=a.set(),n=a.set(),o=a.set(),p=Math.max.apply(Math,g),q=[],r=0,s=h.colors||i.colors,t=g.length;if(Raphael.is(g[0],"array")){p=[],r=t,t=0;for(var u=g.length;u--;)m.push(a.set()),p.push(Math.max.apply(Math,g[u])),t=Math.max(t,g[u].length);if(h.stacked)for(var u=t;u--;){for(var v=0,w=g.length;w--;)v+=+g[w][u]||0;q.push(v)}for(var u=g.length;u--;)if(t>g[u].length)for(var w=t;w--;)g[u].push(0);p=Math.max.apply(Math,h.stacked?q:p)}p=h.to||p;var x=Math.floor(100*(f/(t*(100+k)+k))),y=Math.floor(x*k/100),z=[],A=d+y,B=(e-1)/p;!h.stacked&&(x/=r||1);for(var u=0;t>u;u++){z=[];for(var w=0;(r||1)>w;w++){var C=r?g[w][u]:g[u],D=c(b,A+x/2,Math.round(C*B),x-1,!1,j,null,a).attr({stroke:"none",fill:s[r?w:u]});r?m[w].push(D):m.push(D),D.x=b+Math.round(C*B),D.y=A+x/2,D.w=Math.round(C*B),D.h=x,D.value=+C,h.stacked?z.push(D):A+=x}if(h.stacked){var E=a.rect(b,z[0].y-z[0].h/2,e,x).attr(i.shim);o.push(E),E.bars=a.set();for(var F=0,G=z.length;G--;)z[G].toFront();for(var G=0,H=z.length;H>G;G++){var I,D=z[G],C=Math.round((F+D.value)*B),J=c(b,D.y,C,x-1,!1,j,1,a);E.bars.push(D),F&&D.attr({path:J}),D.w=C,D.x=b+C,n.push(I=a.rect(b+F*B,D.y-D.h/2,D.value*B,x).attr(i.shim)),I.bar=D,F+=D.value}A+=x}A+=y}if(o.toFront(),A=d+y,!h.stacked)for(var u=0;t>u;u++){for(var w=0;(r||1)>w;w++){var I=a.rect(b,A,e,x).attr(i.shim);n.push(I),I.bar=r?m[w][u]:m[u],I.value=I.bar.value,A+=x}A+=y}return l.label=function(c,d){c=c||[],this.labels=a.set();for(var e=0;t>e;e++)for(var f=0;r>f;f++){var o,j=i.labelise(r?c[f]&&c[f][e]:c[e],r?g[f][e]:g[e],p),k=d?m[f][e].x-x/2+3:b+5;this.labels.push(o=a.text(k,m[f][e].y,j).attr(i.txtattr).attr({fill:h.legendcolor||"#000","text-anchor":"start"}).insertBefore(n[0])),b+5>o.getBBox().x?o.attr({x:b+5,"text-anchor":"start"}):m[f][e].label=o}return this},l.hover=function(a,b){return o.hide(),n.show(),b=b||function(){},n.mouseover(a).mouseout(b),this},l.hoverColumn=function(a,b){return n.hide(),o.show(),b=b||function(){},o.mouseover(a).mouseout(b),this},l.each=function(a){if(!Raphael.is(a,"function"))return this;for(var b=n.length;b--;)a.call(n[b]);return this},l.eachColumn=function(a){if(!Raphael.is(a,"function"))return this;for(var b=o.length;b--;)a.call(o[b]);return this},l.click=function(a){return o.hide(),n.show(),n.click(a),this},l.clickColumn=function(a){return n.hide(),o.show(),o.click(a),this},l.push(m,n,o),l.bars=m,l.covers=n,l}var a=Math.min,b=Math.max,f=function(){};f.prototype=Raphael.g,e.prototype=d.prototype=new f,Raphael.fn.hbarchart=function(a,b,c,d,f,g){return new e(this,a,b,c,d,f,g)},Raphael.fn.barchart=function(a,b,c,e,f,g){return new d(this,a,b,c,e,f,g)}})(); \ No newline at end of file
diff --git a/vendor/assets/javascripts/g.bar.js b/vendor/assets/javascripts/g.bar.js
new file mode 100644
index 00000000000..166bd654d6e
--- /dev/null
+++ b/vendor/assets/javascripts/g.bar.js
@@ -0,0 +1,674 @@
+/*!
+ * g.Raphael 0.51 - Charting library, based on Raphaël
+ *
+ * Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
+ * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
+ */
+(function () {
+ var mmin = Math.min,
+ mmax = Math.max;
+
+ function finger(x, y, width, height, dir, ending, isPath, paper) {
+ var path,
+ ends = { round: 'round', sharp: 'sharp', soft: 'soft', square: 'square' };
+
+ // dir 0 for horizontal and 1 for vertical
+ if ((dir && !height) || (!dir && !width)) {
+ return isPath ? "" : paper.path();
+ }
+
+ ending = ends[ending] || "square";
+ height = Math.round(height);
+ width = Math.round(width);
+ x = Math.round(x);
+ y = Math.round(y);
+
+ switch (ending) {
+ case "round":
+ if (!dir) {
+ var r = ~~(height / 2);
+
+ if (width < r) {
+ r = width;
+ path = [
+ "M", x + .5, y + .5 - ~~(height / 2),
+ "l", 0, 0,
+ "a", r, ~~(height / 2), 0, 0, 1, 0, height,
+ "l", 0, 0,
+ "z"
+ ];
+ } else {
+ path = [
+ "M", x + .5, y + .5 - r,
+ "l", width - r, 0,
+ "a", r, r, 0, 1, 1, 0, height,
+ "l", r - width, 0,
+ "z"
+ ];
+ }
+ } else {
+ r = ~~(width / 2);
+
+ if (height < r) {
+ r = height;
+ path = [
+ "M", x - ~~(width / 2), y,
+ "l", 0, 0,
+ "a", ~~(width / 2), r, 0, 0, 1, width, 0,
+ "l", 0, 0,
+ "z"
+ ];
+ } else {
+ path = [
+ "M", x - r, y,
+ "l", 0, r - height,
+ "a", r, r, 0, 1, 1, width, 0,
+ "l", 0, height - r,
+ "z"
+ ];
+ }
+ }
+ break;
+ case "sharp":
+ if (!dir) {
+ var half = ~~(height / 2);
+
+ path = [
+ "M", x, y + half,
+ "l", 0, -height, mmax(width - half, 0), 0, mmin(half, width), half, -mmin(half, width), half + (half * 2 < height),
+ "z"
+ ];
+ } else {
+ half = ~~(width / 2);
+ path = [
+ "M", x + half, y,
+ "l", -width, 0, 0, -mmax(height - half, 0), half, -mmin(half, height), half, mmin(half, height), half,
+ "z"
+ ];
+ }
+ break;
+ case "square":
+ if (!dir) {
+ path = [
+ "M", x, y + ~~(height / 2),
+ "l", 0, -height, width, 0, 0, height,
+ "z"
+ ];
+ } else {
+ path = [
+ "M", x + ~~(width / 2), y,
+ "l", 1 - width, 0, 0, -height, width - 1, 0,
+ "z"
+ ];
+ }
+ break;
+ case "soft":
+ if (!dir) {
+ r = mmin(width, Math.round(height / 5));
+ path = [
+ "M", x + .5, y + .5 - ~~(height / 2),
+ "l", width - r, 0,
+ "a", r, r, 0, 0, 1, r, r,
+ "l", 0, height - r * 2,
+ "a", r, r, 0, 0, 1, -r, r,
+ "l", r - width, 0,
+ "z"
+ ];
+ } else {
+ r = mmin(Math.round(width / 5), height);
+ path = [
+ "M", x - ~~(width / 2), y,
+ "l", 0, r - height,
+ "a", r, r, 0, 0, 1, r, -r,
+ "l", width - 2 * r, 0,
+ "a", r, r, 0, 0, 1, r, r,
+ "l", 0, height - r,
+ "z"
+ ];
+ }
+ }
+
+ if (isPath) {
+ return path.join(",");
+ } else {
+ return paper.path(path);
+ }
+ }
+
+/*\
+ * Paper.vbarchart
+ [ method ]
+ **
+ * Creates a vertical bar chart
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the chart
+ - y (number) y coordinate of the chart
+ - width (number) width of the chart (respected by all elements in the set)
+ - height (number) height of the chart (respected by all elements in the set)
+ - values (array) values
+ - opts (object) options for the chart
+ o {
+ o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
+ o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
+ o vgutter (number)
+ o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
+ o stacked (boolean) whether or not to tread values as in a stacked bar chart
+ o to
+ o stretch (boolean)
+ o }
+ **
+ = (object) path element of the popup
+ > Usage
+ | r.vbarchart(0, 0, 620, 260, [76, 70, 67, 71, 69], {})
+ \*/
+
+ function VBarchart(paper, x, y, width, height, values, opts) {
+ opts = opts || {};
+
+ var chartinst = this,
+ type = opts.type || "square",
+ gutter = parseFloat(opts.gutter || "20%"),
+ chart = paper.set(),
+ bars = paper.set(),
+ covers = paper.set(),
+ covers2 = paper.set(),
+ total = Math.max.apply(Math, values),
+ stacktotal = [],
+ multi = 0,
+ colors = opts.colors || chartinst.colors,
+ len = values.length;
+
+ if (Raphael.is(values[0], "array")) {
+ total = [];
+ multi = len;
+ len = 0;
+
+ for (var i = values.length; i--;) {
+ bars.push(paper.set());
+ total.push(Math.max.apply(Math, values[i]));
+ len = Math.max(len, values[i].length);
+ }
+
+ if (opts.stacked) {
+ for (var i = len; i--;) {
+ var tot = 0;
+
+ for (var j = values.length; j--;) {
+ tot +=+ values[j][i] || 0;
+ }
+
+ stacktotal.push(tot);
+ }
+ }
+
+ for (var i = values.length; i--;) {
+ if (values[i].length < len) {
+ for (var j = len; j--;) {
+ values[i].push(0);
+ }
+ }
+ }
+
+ total = Math.max.apply(Math, opts.stacked ? stacktotal : total);
+ }
+
+ total = (opts.to) || total;
+
+ var barwidth = width / (len * (100 + gutter) + gutter) * 100,
+ barhgutter = barwidth * gutter / 100,
+ barvgutter = opts.vgutter == null ? 20 : opts.vgutter,
+ stack = [],
+ X = x + barhgutter,
+ Y = (height - 2 * barvgutter) / total;
+
+ if (!opts.stretch) {
+ barhgutter = Math.round(barhgutter);
+ barwidth = Math.floor(barwidth);
+ }
+
+ !opts.stacked && (barwidth /= multi || 1);
+
+ for (var i = 0; i < len; i++) {
+ stack = [];
+
+ for (var j = 0; j < (multi || 1); j++) {
+ var h = Math.round((multi ? values[j][i] : values[i]) * Y),
+ top = y + height - barvgutter - h,
+ bar = finger(Math.round(X + barwidth / 2), top + h, barwidth, h, true, type, null, paper).attr({ stroke: "none", fill: colors[multi ? j : i] });
+
+ if (multi) {
+ bars[j].push(bar);
+ } else {
+ bars.push(bar);
+ }
+
+ bar.y = top;
+ bar.x = Math.round(X + barwidth / 2);
+ bar.w = barwidth;
+ bar.h = h;
+ bar.value = multi ? values[j][i] : values[i];
+
+ if (!opts.stacked) {
+ X += barwidth;
+ } else {
+ stack.push(bar);
+ }
+ }
+
+ if (opts.stacked) {
+ var cvr;
+
+ covers2.push(cvr = paper.rect(stack[0].x - stack[0].w / 2, y, barwidth, height).attr(chartinst.shim));
+ cvr.bars = paper.set();
+
+ var size = 0;
+
+ for (var s = stack.length; s--;) {
+ stack[s].toFront();
+ }
+
+ for (var s = 0, ss = stack.length; s < ss; s++) {
+ var bar = stack[s],
+ cover,
+ h = (size + bar.value) * Y,
+ path = finger(bar.x, y + height - barvgutter - !!size * .5, barwidth, h, true, type, 1, paper);
+
+ cvr.bars.push(bar);
+ size && bar.attr({path: path});
+ bar.h = h;
+ bar.y = y + height - barvgutter - !!size * .5 - h;
+ covers.push(cover = paper.rect(bar.x - bar.w / 2, bar.y, barwidth, bar.value * Y).attr(chartinst.shim));
+ cover.bar = bar;
+ cover.value = bar.value;
+ size += bar.value;
+ }
+
+ X += barwidth;
+ }
+
+ X += barhgutter;
+ }
+
+ covers2.toFront();
+ X = x + barhgutter;
+
+ if (!opts.stacked) {
+ for (var i = 0; i < len; i++) {
+ for (var j = 0; j < (multi || 1); j++) {
+ var cover;
+
+ covers.push(cover = paper.rect(Math.round(X), y + barvgutter, barwidth, height - barvgutter).attr(chartinst.shim));
+ cover.bar = multi ? bars[j][i] : bars[i];
+ cover.value = cover.bar.value;
+ X += barwidth;
+ }
+
+ X += barhgutter;
+ }
+ }
+
+ chart.label = function (labels, isBottom) {
+ labels = labels || [];
+ this.labels = paper.set();
+
+ var L, l = -Infinity;
+
+ if (opts.stacked) {
+ for (var i = 0; i < len; i++) {
+ var tot = 0;
+
+ for (var j = 0; j < (multi || 1); j++) {
+ tot += multi ? values[j][i] : values[i];
+
+ if (j == multi - 1) {
+ var label = paper.labelise(labels[i], tot, total);
+
+ L = paper.text(bars[i * (multi || 1) + j].x, y + height - barvgutter / 2, label).attr(txtattr).insertBefore(covers[i * (multi || 1) + j]);
+
+ var bb = L.getBBox();
+
+ if (bb.x - 7 < l) {
+ L.remove();
+ } else {
+ this.labels.push(L);
+ l = bb.x + bb.width;
+ }
+ }
+ }
+ }
+ } else {
+ for (var i = 0; i < len; i++) {
+ for (var j = 0; j < (multi || 1); j++) {
+ var label = paper.labelise(multi ? labels[j] && labels[j][i] : labels[i], multi ? values[j][i] : values[i], total);
+
+ L = paper.text(bars[i * (multi || 1) + j].x, isBottom ? y + height - barvgutter / 2 : bars[i * (multi || 1) + j].y - 10, label).attr(txtattr).insertBefore(covers[i * (multi || 1) + j]);
+
+ var bb = L.getBBox();
+
+ if (bb.x - 7 < l) {
+ L.remove();
+ } else {
+ this.labels.push(L);
+ l = bb.x + bb.width;
+ }
+ }
+ }
+ }
+ return this;
+ };
+
+ chart.hover = function (fin, fout) {
+ covers2.hide();
+ covers.show();
+ covers.mouseover(fin).mouseout(fout);
+ return this;
+ };
+
+ chart.hoverColumn = function (fin, fout) {
+ covers.hide();
+ covers2.show();
+ fout = fout || function () {};
+ covers2.mouseover(fin).mouseout(fout);
+ return this;
+ };
+
+ chart.click = function (f) {
+ covers2.hide();
+ covers.show();
+ covers.click(f);
+ return this;
+ };
+
+ chart.each = function (f) {
+ if (!Raphael.is(f, "function")) {
+ return this;
+ }
+ for (var i = covers.length; i--;) {
+ f.call(covers[i]);
+ }
+ return this;
+ };
+
+ chart.eachColumn = function (f) {
+ if (!Raphael.is(f, "function")) {
+ return this;
+ }
+ for (var i = covers2.length; i--;) {
+ f.call(covers2[i]);
+ }
+ return this;
+ };
+
+ chart.clickColumn = function (f) {
+ covers.hide();
+ covers2.show();
+ covers2.click(f);
+ return this;
+ };
+
+ chart.push(bars, covers, covers2);
+ chart.bars = bars;
+ chart.covers = covers;
+ return chart;
+ };
+
+ //inheritance
+ var F = function() {};
+ F.prototype = Raphael.g;
+ HBarchart.prototype = VBarchart.prototype = new F; //prototype reused by hbarchart
+
+ Raphael.fn.barchart = function(x, y, width, height, values, opts) {
+ return new VBarchart(this, x, y, width, height, values, opts);
+ };
+
+/*\
+ * Paper.barchart
+ [ method ]
+ **
+ * Creates a horizontal bar chart
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the chart
+ - y (number) y coordinate of the chart
+ - width (number) width of the chart (respected by all elements in the set)
+ - height (number) height of the chart (respected by all elements in the set)
+ - values (array) values
+ - opts (object) options for the chart
+ o {
+ o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
+ o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
+ o vgutter (number)
+ o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
+ o stacked (boolean) whether or not to tread values as in a stacked bar chart
+ o to
+ o stretch (boolean)
+ o }
+ **
+ = (object) path element of the popup
+ > Usage
+ | r.barchart(0, 0, 620, 260, [76, 70, 67, 71, 69], {})
+ \*/
+
+ function HBarchart(paper, x, y, width, height, values, opts) {
+ opts = opts || {};
+
+ var chartinst = this,
+ type = opts.type || "square",
+ gutter = parseFloat(opts.gutter || "20%"),
+ chart = paper.set(),
+ bars = paper.set(),
+ covers = paper.set(),
+ covers2 = paper.set(),
+ total = Math.max.apply(Math, values),
+ stacktotal = [],
+ multi = 0,
+ colors = opts.colors || chartinst.colors,
+ len = values.length;
+
+ if (Raphael.is(values[0], "array")) {
+ total = [];
+ multi = len;
+ len = 0;
+
+ for (var i = values.length; i--;) {
+ bars.push(paper.set());
+ total.push(Math.max.apply(Math, values[i]));
+ len = Math.max(len, values[i].length);
+ }
+
+ if (opts.stacked) {
+ for (var i = len; i--;) {
+ var tot = 0;
+ for (var j = values.length; j--;) {
+ tot +=+ values[j][i] || 0;
+ }
+ stacktotal.push(tot);
+ }
+ }
+
+ for (var i = values.length; i--;) {
+ if (values[i].length < len) {
+ for (var j = len; j--;) {
+ values[i].push(0);
+ }
+ }
+ }
+
+ total = Math.max.apply(Math, opts.stacked ? stacktotal : total);
+ }
+
+ total = (opts.to) || total;
+
+ var barheight = Math.floor(height / (len * (100 + gutter) + gutter) * 100),
+ bargutter = Math.floor(barheight * gutter / 100),
+ stack = [],
+ Y = y + bargutter,
+ X = (width - 1) / total;
+
+ !opts.stacked && (barheight /= multi || 1);
+
+ for (var i = 0; i < len; i++) {
+ stack = [];
+
+ for (var j = 0; j < (multi || 1); j++) {
+ var val = multi ? values[j][i] : values[i],
+ bar = finger(x, Y + barheight / 2, Math.round(val * X), barheight - 1, false, type, null, paper).attr({stroke: "none", fill: colors[multi ? j : i]});
+
+ if (multi) {
+ bars[j].push(bar);
+ } else {
+ bars.push(bar);
+ }
+
+ bar.x = x + Math.round(val * X);
+ bar.y = Y + barheight / 2;
+ bar.w = Math.round(val * X);
+ bar.h = barheight;
+ bar.value = +val;
+
+ if (!opts.stacked) {
+ Y += barheight;
+ } else {
+ stack.push(bar);
+ }
+ }
+
+ if (opts.stacked) {
+ var cvr = paper.rect(x, stack[0].y - stack[0].h / 2, width, barheight).attr(chartinst.shim);
+
+ covers2.push(cvr);
+ cvr.bars = paper.set();
+
+ var size = 0;
+
+ for (var s = stack.length; s--;) {
+ stack[s].toFront();
+ }
+
+ for (var s = 0, ss = stack.length; s < ss; s++) {
+ var bar = stack[s],
+ cover,
+ val = Math.round((size + bar.value) * X),
+ path = finger(x, bar.y, val, barheight - 1, false, type, 1, paper);
+
+ cvr.bars.push(bar);
+ size && bar.attr({ path: path });
+ bar.w = val;
+ bar.x = x + val;
+ covers.push(cover = paper.rect(x + size * X, bar.y - bar.h / 2, bar.value * X, barheight).attr(chartinst.shim));
+ cover.bar = bar;
+ size += bar.value;
+ }
+
+ Y += barheight;
+ }
+
+ Y += bargutter;
+ }
+
+ covers2.toFront();
+ Y = y + bargutter;
+
+ if (!opts.stacked) {
+ for (var i = 0; i < len; i++) {
+ for (var j = 0; j < (multi || 1); j++) {
+ var cover = paper.rect(x, Y, width, barheight).attr(chartinst.shim);
+
+ covers.push(cover);
+ cover.bar = multi ? bars[j][i] : bars[i];
+ cover.value = cover.bar.value;
+ Y += barheight;
+ }
+
+ Y += bargutter;
+ }
+ }
+
+ chart.label = function (labels, isRight) {
+ labels = labels || [];
+ this.labels = paper.set();
+
+ for (var i = 0; i < len; i++) {
+ for (var j = 0; j < multi; j++) {
+ var label = paper.labelise(multi ? labels[j] && labels[j][i] : labels[i], multi ? values[j][i] : values[i], total),
+ X = isRight ? bars[i * (multi || 1) + j].x - barheight / 2 + 3 : x + 5,
+ A = isRight ? "end" : "start",
+ L;
+
+ this.labels.push(L = paper.text(X, bars[i * (multi || 1) + j].y, label).attr(txtattr).attr({ "text-anchor": A }).insertBefore(covers[0]));
+
+ if (L.getBBox().x < x + 5) {
+ L.attr({x: x + 5, "text-anchor": "start"});
+ } else {
+ bars[i * (multi || 1) + j].label = L;
+ }
+ }
+ }
+
+ return this;
+ };
+
+ chart.hover = function (fin, fout) {
+ covers2.hide();
+ covers.show();
+ fout = fout || function () {};
+ covers.mouseover(fin).mouseout(fout);
+ return this;
+ };
+
+ chart.hoverColumn = function (fin, fout) {
+ covers.hide();
+ covers2.show();
+ fout = fout || function () {};
+ covers2.mouseover(fin).mouseout(fout);
+ return this;
+ };
+
+ chart.each = function (f) {
+ if (!Raphael.is(f, "function")) {
+ return this;
+ }
+ for (var i = covers.length; i--;) {
+ f.call(covers[i]);
+ }
+ return this;
+ };
+
+ chart.eachColumn = function (f) {
+ if (!Raphael.is(f, "function")) {
+ return this;
+ }
+ for (var i = covers2.length; i--;) {
+ f.call(covers2[i]);
+ }
+ return this;
+ };
+
+ chart.click = function (f) {
+ covers2.hide();
+ covers.show();
+ covers.click(f);
+ return this;
+ };
+
+ chart.clickColumn = function (f) {
+ covers.hide();
+ covers2.show();
+ covers2.click(f);
+ return this;
+ };
+
+ chart.push(bars, covers, covers2);
+ chart.bars = bars;
+ chart.covers = covers;
+ return chart;
+ };
+
+ Raphael.fn.hbarchart = function(x, y, width, height, values, opts) {
+ return new HBarchart(this, x, y, width, height, values, opts);
+ };
+
+})();
diff --git a/vendor/assets/javascripts/g.raphael-min.js b/vendor/assets/javascripts/g.raphael-min.js
deleted file mode 100644
index f8b381c623b..00000000000
--- a/vendor/assets/javascripts/g.raphael-min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * g.Raphael 0.51 - Charting library, based on Raphaël
- *
- * Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
- * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
- */
-Raphael.el.popup=function(a,b,c,d){var f,g,h,i,j,e=this.paper||this[0].paper;if(e){switch(this.type){case"text":case"circle":case"ellipse":h=!0;break;default:h=!1}a=null==a?"up":a,b=b||5,f=this.getBBox(),c="number"==typeof c?c:h?f.x+f.width/2:f.x,d="number"==typeof d?d:h?f.y+f.height/2:f.y,i=Math.max(f.width/2-b,0),j=Math.max(f.height/2-b,0),this.translate(c-f.x-(h?f.width/2:0),d-f.y-(h?f.height/2:0)),f=this.getBBox();var k={up:["M",c,d,"l",-b,-b,-i,0,"a",b,b,0,0,1,-b,-b,"l",0,-f.height,"a",b,b,0,0,1,b,-b,"l",2*b+2*i,0,"a",b,b,0,0,1,b,b,"l",0,f.height,"a",b,b,0,0,1,-b,b,"l",-i,0,"z"].join(","),down:["M",c,d,"l",b,b,i,0,"a",b,b,0,0,1,b,b,"l",0,f.height,"a",b,b,0,0,1,-b,b,"l",-(2*b+2*i),0,"a",b,b,0,0,1,-b,-b,"l",0,-f.height,"a",b,b,0,0,1,b,-b,"l",i,0,"z"].join(","),left:["M",c,d,"l",-b,b,0,j,"a",b,b,0,0,1,-b,b,"l",-f.width,0,"a",b,b,0,0,1,-b,-b,"l",0,-(2*b+2*j),"a",b,b,0,0,1,b,-b,"l",f.width,0,"a",b,b,0,0,1,b,b,"l",0,j,"z"].join(","),right:["M",c,d,"l",b,-b,0,-j,"a",b,b,0,0,1,b,-b,"l",f.width,0,"a",b,b,0,0,1,b,b,"l",0,2*b+2*j,"a",b,b,0,0,1,-b,b,"l",-f.width,0,"a",b,b,0,0,1,-b,-b,"l",0,-j,"z"].join(",")};return g={up:{x:-!h*(f.width/2),y:2*-b-(h?f.height/2:f.height)},down:{x:-!h*(f.width/2),y:2*b+(h?f.height/2:f.height)},left:{x:2*-b-(h?f.width/2:f.width),y:-!h*(f.height/2)},right:{x:2*b+(h?f.width/2:f.width),y:-!h*(f.height/2)}}[a],this.translate(g.x,g.y),e.path(k[a]).attr({fill:"#000",stroke:"none"}).insertBefore(this.node?this:this[0])}},Raphael.el.tag=function(a,b,c,d){var e=3,f=this.paper||this[0].paper;if(f){var i,j,k,g=f.path().attr({fill:"#000",stroke:"#000"}),h=this.getBBox();switch(this.type){case"text":case"circle":case"ellipse":k=!0;break;default:k=!1}return a=a||0,c="number"==typeof c?c:k?h.x+h.width/2:h.x,d="number"==typeof d?d:k?h.y+h.height/2:h.y,b=null==b?5:b,j=.5522*b,h.height>=2*b?g.attr({path:["M",c,d+b,"a",b,b,0,1,1,0,2*-b,b,b,0,1,1,0,2*b,"m",0,2*-b-e,"a",b+e,b+e,0,1,0,0,2*(b+e),"L",c+b+e,d+h.height/2+e,"l",h.width+2*e,0,0,-h.height-2*e,-h.width-2*e,0,"L",c,d-b-e].join(",")}):(i=Math.sqrt(Math.pow(b+e,2)-Math.pow(h.height/2+e,2)),g.attr({path:["M",c,d+b,"c",-j,0,-b,j-b,-b,-b,0,-j,b-j,-b,b,-b,j,0,b,b-j,b,b,0,j,j-b,b,-b,b,"M",c+i,d-h.height/2-e,"a",b+e,b+e,0,1,0,0,h.height+2*e,"l",b+e-i+h.width+2*e,0,0,-h.height-2*e,"L",c+i,d-h.height/2-e].join(",")})),a=360-a,g.rotate(a,c,d),this.attrs?(this.attr(this.attrs.x?"x":"cx",c+b+e+(k?h.width/2:"text"==this.type?h.width:0)).attr("y",k?d:d-h.height/2),this.rotate(a,c,d),a>90&&270>a&&this.attr(this.attrs.x?"x":"cx",c-b-e-(k?h.width/2:h.width)).rotate(180,c,d)):a>90&&270>a?(this.translate(c-h.x-h.width-b-e,d-h.y-h.height/2),this.rotate(a-180,h.x+h.width+b+e,h.y+h.height/2)):(this.translate(c-h.x+b+e,d-h.y-h.height/2),this.rotate(a,h.x-b-e,h.y+h.height/2)),g.insertBefore(this.node?this:this[0])}},Raphael.el.drop=function(a,b,c){var f,g,h,i,j,d=this.getBBox(),e=this.paper||this[0].paper;if(e){switch(this.type){case"text":case"circle":case"ellipse":f=!0;break;default:f=!1}return a=a||0,b="number"==typeof b?b:f?d.x+d.width/2:d.x,c="number"==typeof c?c:f?d.y+d.height/2:d.y,g=Math.max(d.width,d.height)+Math.min(d.width,d.height),h=e.path(["M",b,c,"l",g,0,"A",.4*g,.4*g,0,1,0,b+.7*g,c-.7*g,"z"]).attr({fill:"#000",stroke:"none"}).rotate(22.5-a,b,c),a=(a+90)*Math.PI/180,i=b+g*Math.sin(a)-(f?0:d.width/2),j=c+g*Math.cos(a)-(f?0:d.height/2),this.attrs?this.attr(this.attrs.x?"x":"cx",i).attr(this.attrs.y?"y":"cy",j):this.translate(i-d.x,j-d.y),h.insertBefore(this.node?this:this[0])}},Raphael.el.flag=function(a,b,c){var d=3,e=this.paper||this[0].paper;if(e){var i,f=e.path().attr({fill:"#000",stroke:"#000"}),g=this.getBBox(),h=g.height/2;switch(this.type){case"text":case"circle":case"ellipse":i=!0;break;default:i=!1}return a=a||0,b="number"==typeof b?b:i?g.x+g.width/2:g.x,c="number"==typeof c?c:i?g.y+g.height/2:g.y,f.attr({path:["M",b,c,"l",h+d,-h-d,g.width+2*d,0,0,g.height+2*d,-g.width-2*d,0,"z"].join(",")}),a=360-a,f.rotate(a,b,c),this.attrs?(this.attr(this.attrs.x?"x":"cx",b+h+d+(i?g.width/2:"text"==this.type?g.width:0)).attr("y",i?c:c-g.height/2),this.rotate(a,b,c),a>90&&270>a&&this.attr(this.attrs.x?"x":"cx",b-h-d-(i?g.width/2:g.width)).rotate(180,b,c)):a>90&&270>a?(this.translate(b-g.x-g.width-h-d,c-g.y-g.height/2),this.rotate(a-180,g.x+g.width+h+d,g.y+g.height/2)):(this.translate(b-g.x+h+d,c-g.y-g.height/2),this.rotate(a,g.x-h-d,g.y+g.height/2)),f.insertBefore(this.node?this:this[0])}},Raphael.el.label=function(){var a=this.getBBox(),b=this.paper||this[0].paper,c=Math.min(20,a.width+10,a.height+10)/2;if(b)return b.rect(a.x-c/2,a.y-c/2,a.width+c,a.height+c,c).attr({stroke:"none",fill:"#000"}).insertBefore(this.node?this:this[0])},Raphael.el.blob=function(a,b,c){var g,h,i,d=this.getBBox(),e=Math.PI/180,f=this.paper||this[0].paper;if(f){switch(this.type){case"text":case"circle":case"ellipse":h=!0;break;default:h=!1}g=f.path().attr({fill:"#000",stroke:"none"}),a=(+a+1?a:45)+90,i=Math.min(d.height,d.width),b="number"==typeof b?b:h?d.x+d.width/2:d.x,c="number"==typeof c?c:h?d.y+d.height/2:d.y;var j=Math.max(d.width+i,25*i/12),k=Math.max(d.height+i,25*i/12),l=b+i*Math.sin((a-22.5)*e),m=c+i*Math.cos((a-22.5)*e),n=b+i*Math.sin((a+22.5)*e),o=c+i*Math.cos((a+22.5)*e),p=(n-l)/2,q=(o-m)/2,r=j/2,s=k/2,t=-Math.sqrt(Math.abs(r*r*s*s-r*r*q*q-s*s*p*p)/(r*r*q*q+s*s*p*p)),u=t*r*q/s+(n+l)/2,v=t*-s*p/r+(o+m)/2;return g.attr({x:u,y:v,path:["M",b,c,"L",n,o,"A",r,s,0,1,1,l,m,"z"].join(",")}),this.translate(u-d.x-d.width/2,v-d.y-d.height/2),g.insertBefore(this.node?this:this[0])}},Raphael.fn.label=function(a,b,c){var d=this.set();return c=this.text(a,b,c).attr(Raphael.g.txtattr),d.push(c.label(),c)},Raphael.fn.popup=function(a,b,c,d,e){var f=this.set();return c=this.text(a,b,c).attr(Raphael.g.txtattr),f.push(c.popup(d,e),c)},Raphael.fn.tag=function(a,b,c,d,e){var f=this.set();return c=this.text(a,b,c).attr(Raphael.g.txtattr),f.push(c.tag(d,e),c)},Raphael.fn.flag=function(a,b,c,d){var e=this.set();return c=this.text(a,b,c).attr(Raphael.g.txtattr),e.push(c.flag(d),c)},Raphael.fn.drop=function(a,b,c,d){var e=this.set();return c=this.text(a,b,c).attr(Raphael.g.txtattr),e.push(c.drop(d),c)},Raphael.fn.blob=function(a,b,c,d){var e=this.set();return c=this.text(a,b,c).attr(Raphael.g.txtattr),e.push(c.blob(d),c)},Raphael.el.lighter=function(a){a=a||2;var b=[this.attrs.fill,this.attrs.stroke];return this.fs=this.fs||[b[0],b[1]],b[0]=Raphael.rgb2hsb(Raphael.getRGB(b[0]).hex),b[1]=Raphael.rgb2hsb(Raphael.getRGB(b[1]).hex),b[0].b=Math.min(b[0].b*a,1),b[0].s=b[0].s/a,b[1].b=Math.min(b[1].b*a,1),b[1].s=b[1].s/a,this.attr({fill:"hsb("+[b[0].h,b[0].s,b[0].b]+")",stroke:"hsb("+[b[1].h,b[1].s,b[1].b]+")"}),this},Raphael.el.darker=function(a){a=a||2;var b=[this.attrs.fill,this.attrs.stroke];return this.fs=this.fs||[b[0],b[1]],b[0]=Raphael.rgb2hsb(Raphael.getRGB(b[0]).hex),b[1]=Raphael.rgb2hsb(Raphael.getRGB(b[1]).hex),b[0].s=Math.min(b[0].s*a,1),b[0].b=b[0].b/a,b[1].s=Math.min(b[1].s*a,1),b[1].b=b[1].b/a,this.attr({fill:"hsb("+[b[0].h,b[0].s,b[0].b]+")",stroke:"hsb("+[b[1].h,b[1].s,b[1].b]+")"}),this},Raphael.el.resetBrightness=function(){return this.fs&&(this.attr({fill:this.fs[0],stroke:this.fs[1]}),delete this.fs),this},function(){var a=["lighter","darker","resetBrightness"],b=["popup","tag","flag","label","drop","blob"];for(var c in b)(function(a){Raphael.st[a]=function(){return Raphael.el[a].apply(this,arguments)}})(b[c]);for(var c in a)(function(a){Raphael.st[a]=function(){for(var b=0;this.length>b;b++)this[b][a].apply(this[b],arguments);return this}})(a[c])}(),Raphael.g={shim:{stroke:"none",fill:"#000","fill-opacity":0},txtattr:{font:"12px Arial, sans-serif",fill:"#fff"},colors:function(){for(var a=[.6,.2,.05,.1333,.75,0],b=[],c=0;10>c;c++)a.length>c?b.push("hsb("+a[c]+",.75, .75)"):b.push("hsb("+a[c-a.length]+", 1, .5)");return b}(),snapEnds:function(a,b,c){function f(a){return.25>Math.abs(a-.5)?~~a+.5:Math.round(a)}var d=a,e=b;if(d==e)return{from:d,to:e,power:0};var g=(e-d)/c,h=~~g,i=h,j=0;if(h){for(;i;)j--,i=~~(g*Math.pow(10,j))/Math.pow(10,j);j++}else{if(0!=g&&isFinite(g))for(;!h;)j=j||1,h=~~(g*Math.pow(10,j))/Math.pow(10,j),j++;else j=1;j&&j--}return e=f(b*Math.pow(10,j))/Math.pow(10,j),b>e&&(e=f((b+.5)*Math.pow(10,j))/Math.pow(10,j)),d=f((a-(j>0?0:.5))*Math.pow(10,j))/Math.pow(10,j),{from:d,to:e,power:j}},axis:function(a,b,c,d,e,f,g,h,i,j,k){j=null==j?2:j,i=i||"t",f=f||10,k=arguments[arguments.length-1];var t,l="|"==i||" "==i?["M",a+.5,b,"l",0,.001]:1==g||3==g?["M",a+.5,b,"l",0,-c]:["M",a,b+.5,"l",c,0],m=this.snapEnds(d,e,f),n=m.from,o=m.to,p=m.power,q=0,r={font:"11px 'Fontin Sans', Fontin-Sans, sans-serif"},s=k.set();t=(o-n)/f;var u=n,v=p>0?p:0;if(z=c/f,1==+g||3==+g){for(var w=b,x=(g-1?1:-1)*(j+3+!!(g-1));w>=b-c;)"-"!=i&&" "!=i&&(l=l.concat(["M",a-("+"==i||"|"==i?j:2*!(g-1)*j),w+.5,"l",2*j+1,0])),s.push(k.text(a+x,w,h&&h[q++]||(Math.round(u)==u?u:+u.toFixed(v))).attr(r).attr({"text-anchor":g-1?"start":"end"})),u+=t,w-=z;Math.round(w+z-(b-c))&&("-"!=i&&" "!=i&&(l=l.concat(["M",a-("+"==i||"|"==i?j:2*!(g-1)*j),b-c+.5,"l",2*j+1,0])),s.push(k.text(a+x,b-c,h&&h[q]||(Math.round(u)==u?u:+u.toFixed(v))).attr(r).attr({"text-anchor":g-1?"start":"end"})))}else{u=n,v=(p>0)*p,x=(g?-1:1)*(j+9+!g);for(var y=a,z=c/f,A=0,B=0;a+c>=y;){"-"!=i&&" "!=i&&(l=l.concat(["M",y+.5,b-("+"==i?j:2*!!g*j),"l",0,2*j+1])),s.push(A=k.text(y,b+x,h&&h[q++]||(Math.round(u)==u?u:+u.toFixed(v))).attr(r));var C=A.getBBox();B>=C.x-5?s.pop(s.length-1).remove():B=C.x+C.width,u+=t,y+=z}Math.round(y-z-a-c)&&("-"!=i&&" "!=i&&(l=l.concat(["M",a+c+.5,b-("+"==i?j:2*!!g*j),"l",0,2*j+1])),s.push(k.text(a+c,b+x,h&&h[q]||(Math.round(u)==u?u:+u.toFixed(v))).attr(r)))}var D=k.path(l);return D.text=s,D.all=k.set([D,s]),D.remove=function(){this.text.remove(),this.constructor.prototype.remove.call(this)},D},labelise:function(a,b,c){return a?(a+"").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g,function(a,d,e){return d?(+b).toFixed(d.replace(/^#+\.?/g,"").length):e?(100*b/c).toFixed(e.replace(/^%+\.?/g,"").length)+"%":void 0}):(+b).toFixed(0)}}; \ No newline at end of file
diff --git a/vendor/assets/javascripts/g.raphael.js b/vendor/assets/javascripts/g.raphael.js
new file mode 100644
index 00000000000..27f27caf9f2
--- /dev/null
+++ b/vendor/assets/javascripts/g.raphael.js
@@ -0,0 +1,861 @@
+/*!
+ * g.Raphael 0.51 - Charting library, based on Raphaël
+ *
+ * Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
+ * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
+ */
+
+/*
+ * Tooltips on Element prototype
+ */
+/*\
+ * Element.popup
+ [ method ]
+ **
+ * Puts the context Element in a 'popup' tooltip. Can also be used on sets.
+ **
+ > Parameters
+ **
+ - dir (string) location of Element relative to the tail: `'down'`, `'left'`, `'up'` [default], or `'right'`.
+ - size (number) amount of bevel/padding around the Element, as well as half the width and height of the tail [default: `5`]
+ - x (number) x coordinate of the popup's tail [default: Element's `x` or `cx`]
+ - y (number) y coordinate of the popup's tail [default: Element's `y` or `cy`]
+ **
+ = (object) path element of the popup
+ \*/
+Raphael.el.popup = function (dir, size, x, y) {
+ var paper = this.paper || this[0].paper,
+ bb, xy, center, cw, ch;
+
+ if (!paper) return;
+
+ switch (this.type) {
+ case 'text':
+ case 'circle':
+ case 'ellipse': center = true; break;
+ default: center = false;
+ }
+
+ dir = dir == null ? 'up' : dir;
+ size = size || 5;
+ bb = this.getBBox();
+
+ x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
+ y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
+ cw = Math.max(bb.width / 2 - size, 0);
+ ch = Math.max(bb.height / 2 - size, 0);
+
+ this.translate(x - bb.x - (center ? bb.width / 2 : 0), y - bb.y - (center ? bb.height / 2 : 0));
+ bb = this.getBBox();
+
+ var paths = {
+ up: [
+ 'M', x, y,
+ 'l', -size, -size, -cw, 0,
+ 'a', size, size, 0, 0, 1, -size, -size,
+ 'l', 0, -bb.height,
+ 'a', size, size, 0, 0, 1, size, -size,
+ 'l', size * 2 + cw * 2, 0,
+ 'a', size, size, 0, 0, 1, size, size,
+ 'l', 0, bb.height,
+ 'a', size, size, 0, 0, 1, -size, size,
+ 'l', -cw, 0,
+ 'z'
+ ].join(','),
+ down: [
+ 'M', x, y,
+ 'l', size, size, cw, 0,
+ 'a', size, size, 0, 0, 1, size, size,
+ 'l', 0, bb.height,
+ 'a', size, size, 0, 0, 1, -size, size,
+ 'l', -(size * 2 + cw * 2), 0,
+ 'a', size, size, 0, 0, 1, -size, -size,
+ 'l', 0, -bb.height,
+ 'a', size, size, 0, 0, 1, size, -size,
+ 'l', cw, 0,
+ 'z'
+ ].join(','),
+ left: [
+ 'M', x, y,
+ 'l', -size, size, 0, ch,
+ 'a', size, size, 0, 0, 1, -size, size,
+ 'l', -bb.width, 0,
+ 'a', size, size, 0, 0, 1, -size, -size,
+ 'l', 0, -(size * 2 + ch * 2),
+ 'a', size, size, 0, 0, 1, size, -size,
+ 'l', bb.width, 0,
+ 'a', size, size, 0, 0, 1, size, size,
+ 'l', 0, ch,
+ 'z'
+ ].join(','),
+ right: [
+ 'M', x, y,
+ 'l', size, -size, 0, -ch,
+ 'a', size, size, 0, 0, 1, size, -size,
+ 'l', bb.width, 0,
+ 'a', size, size, 0, 0, 1, size, size,
+ 'l', 0, size * 2 + ch * 2,
+ 'a', size, size, 0, 0, 1, -size, size,
+ 'l', -bb.width, 0,
+ 'a', size, size, 0, 0, 1, -size, -size,
+ 'l', 0, -ch,
+ 'z'
+ ].join(',')
+ };
+
+ xy = {
+ up: { x: -!center * (bb.width / 2), y: -size * 2 - (center ? bb.height / 2 : bb.height) },
+ down: { x: -!center * (bb.width / 2), y: size * 2 + (center ? bb.height / 2 : bb.height) },
+ left: { x: -size * 2 - (center ? bb.width / 2 : bb.width), y: -!center * (bb.height / 2) },
+ right: { x: size * 2 + (center ? bb.width / 2 : bb.width), y: -!center * (bb.height / 2) }
+ }[dir];
+
+ this.translate(xy.x, xy.y);
+ return paper.path(paths[dir]).attr({ fill: "#000", stroke: "none" }).insertBefore(this.node ? this : this[0]);
+};
+
+/*\
+ * Element.tag
+ [ method ]
+ **
+ * Puts the context Element in a 'tag' tooltip. Can also be used on sets.
+ **
+ > Parameters
+ **
+ - angle (number) angle of orientation in degrees [default: `0`]
+ - r (number) radius of the loop [default: `5`]
+ - x (number) x coordinate of the center of the tag loop [default: Element's `x` or `cx`]
+ - y (number) y coordinate of the center of the tag loop [default: Element's `x` or `cx`]
+ **
+ = (object) path element of the tag
+ \*/
+Raphael.el.tag = function (angle, r, x, y) {
+ var d = 3,
+ paper = this.paper || this[0].paper;
+
+ if (!paper) return;
+
+ var p = paper.path().attr({ fill: '#000', stroke: '#000' }),
+ bb = this.getBBox(),
+ dx, R, center, tmp;
+
+ switch (this.type) {
+ case 'text':
+ case 'circle':
+ case 'ellipse': center = true; break;
+ default: center = false;
+ }
+
+ angle = angle || 0;
+ x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
+ y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
+ r = r == null ? 5 : r;
+ R = .5522 * r;
+
+ if (bb.height >= r * 2) {
+ p.attr({
+ path: [
+ "M", x, y + r,
+ "a", r, r, 0, 1, 1, 0, -r * 2, r, r, 0, 1, 1, 0, r * 2,
+ "m", 0, -r * 2 -d,
+ "a", r + d, r + d, 0, 1, 0, 0, (r + d) * 2,
+ "L", x + r + d, y + bb.height / 2 + d,
+ "l", bb.width + 2 * d, 0, 0, -bb.height - 2 * d, -bb.width - 2 * d, 0,
+ "L", x, y - r - d
+ ].join(",")
+ });
+ } else {
+ dx = Math.sqrt(Math.pow(r + d, 2) - Math.pow(bb.height / 2 + d, 2));
+ p.attr({
+ path: [
+ "M", x, y + r,
+ "c", -R, 0, -r, R - r, -r, -r, 0, -R, r - R, -r, r, -r, R, 0, r, r - R, r, r, 0, R, R - r, r, -r, r,
+ "M", x + dx, y - bb.height / 2 - d,
+ "a", r + d, r + d, 0, 1, 0, 0, bb.height + 2 * d,
+ "l", r + d - dx + bb.width + 2 * d, 0, 0, -bb.height - 2 * d,
+ "L", x + dx, y - bb.height / 2 - d
+ ].join(",")
+ });
+ }
+
+ angle = 360 - angle;
+ p.rotate(angle, x, y);
+
+ if (this.attrs) {
+ //elements
+ this.attr(this.attrs.x ? 'x' : 'cx', x + r + d + (!center ? this.type == 'text' ? bb.width : 0 : bb.width / 2)).attr('y', center ? y : y - bb.height / 2);
+ this.rotate(angle, x, y);
+ angle > 90 && angle < 270 && this.attr(this.attrs.x ? 'x' : 'cx', x - r - d - (!center ? bb.width : bb.width / 2)).rotate(180, x, y);
+ } else {
+ //sets
+ if (angle > 90 && angle < 270) {
+ this.translate(x - bb.x - bb.width - r - d, y - bb.y - bb.height / 2);
+ this.rotate(angle - 180, bb.x + bb.width + r + d, bb.y + bb.height / 2);
+ } else {
+ this.translate(x - bb.x + r + d, y - bb.y - bb.height / 2);
+ this.rotate(angle, bb.x - r - d, bb.y + bb.height / 2);
+ }
+ }
+
+ return p.insertBefore(this.node ? this : this[0]);
+};
+
+/*\
+ * Element.drop
+ [ method ]
+ **
+ * Puts the context Element in a 'drop' tooltip. Can also be used on sets.
+ **
+ > Parameters
+ **
+ - angle (number) angle of orientation in degrees [default: `0`]
+ - x (number) x coordinate of the drop's point [default: Element's `x` or `cx`]
+ - y (number) y coordinate of the drop's point [default: Element's `x` or `cx`]
+ **
+ = (object) path element of the drop
+ \*/
+Raphael.el.drop = function (angle, x, y) {
+ var bb = this.getBBox(),
+ paper = this.paper || this[0].paper,
+ center, size, p, dx, dy;
+
+ if (!paper) return;
+
+ switch (this.type) {
+ case 'text':
+ case 'circle':
+ case 'ellipse': center = true; break;
+ default: center = false;
+ }
+
+ angle = angle || 0;
+
+ x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
+ y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
+ size = Math.max(bb.width, bb.height) + Math.min(bb.width, bb.height);
+ p = paper.path([
+ "M", x, y,
+ "l", size, 0,
+ "A", size * .4, size * .4, 0, 1, 0, x + size * .7, y - size * .7,
+ "z"
+ ]).attr({fill: "#000", stroke: "none"}).rotate(22.5 - angle, x, y);
+
+ angle = (angle + 90) * Math.PI / 180;
+ dx = (x + size * Math.sin(angle)) - (center ? 0 : bb.width / 2);
+ dy = (y + size * Math.cos(angle)) - (center ? 0 : bb.height / 2);
+
+ this.attrs ?
+ this.attr(this.attrs.x ? 'x' : 'cx', dx).attr(this.attrs.y ? 'y' : 'cy', dy) :
+ this.translate(dx - bb.x, dy - bb.y);
+
+ return p.insertBefore(this.node ? this : this[0]);
+};
+
+/*\
+ * Element.flag
+ [ method ]
+ **
+ * Puts the context Element in a 'flag' tooltip. Can also be used on sets.
+ **
+ > Parameters
+ **
+ - angle (number) angle of orientation in degrees [default: `0`]
+ - x (number) x coordinate of the flag's point [default: Element's `x` or `cx`]
+ - y (number) y coordinate of the flag's point [default: Element's `x` or `cx`]
+ **
+ = (object) path element of the flag
+ \*/
+Raphael.el.flag = function (angle, x, y) {
+ var d = 3,
+ paper = this.paper || this[0].paper;
+
+ if (!paper) return;
+
+ var p = paper.path().attr({ fill: '#000', stroke: '#000' }),
+ bb = this.getBBox(),
+ h = bb.height / 2,
+ center;
+
+ switch (this.type) {
+ case 'text':
+ case 'circle':
+ case 'ellipse': center = true; break;
+ default: center = false;
+ }
+
+ angle = angle || 0;
+ x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
+ y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2: bb.y);
+
+ p.attr({
+ path: [
+ "M", x, y,
+ "l", h + d, -h - d, bb.width + 2 * d, 0, 0, bb.height + 2 * d, -bb.width - 2 * d, 0,
+ "z"
+ ].join(",")
+ });
+
+ angle = 360 - angle;
+ p.rotate(angle, x, y);
+
+ if (this.attrs) {
+ //elements
+ this.attr(this.attrs.x ? 'x' : 'cx', x + h + d + (!center ? this.type == 'text' ? bb.width : 0 : bb.width / 2)).attr('y', center ? y : y - bb.height / 2);
+ this.rotate(angle, x, y);
+ angle > 90 && angle < 270 && this.attr(this.attrs.x ? 'x' : 'cx', x - h - d - (!center ? bb.width : bb.width / 2)).rotate(180, x, y);
+ } else {
+ //sets
+ if (angle > 90 && angle < 270) {
+ this.translate(x - bb.x - bb.width - h - d, y - bb.y - bb.height / 2);
+ this.rotate(angle - 180, bb.x + bb.width + h + d, bb.y + bb.height / 2);
+ } else {
+ this.translate(x - bb.x + h + d, y - bb.y - bb.height / 2);
+ this.rotate(angle, bb.x - h - d, bb.y + bb.height / 2);
+ }
+ }
+
+ return p.insertBefore(this.node ? this : this[0]);
+};
+
+/*\
+ * Element.label
+ [ method ]
+ **
+ * Puts the context Element in a 'label' tooltip. Can also be used on sets.
+ **
+ = (object) path element of the label.
+ \*/
+Raphael.el.label = function () {
+ var bb = this.getBBox(),
+ paper = this.paper || this[0].paper,
+ r = Math.min(20, bb.width + 10, bb.height + 10) / 2;
+
+ if (!paper) return;
+
+ return paper.rect(bb.x - r / 2, bb.y - r / 2, bb.width + r, bb.height + r, r).attr({ stroke: 'none', fill: '#000' }).insertBefore(this.node ? this : this[0]);
+};
+
+/*\
+ * Element.blob
+ [ method ]
+ **
+ * Puts the context Element in a 'blob' tooltip. Can also be used on sets.
+ **
+ > Parameters
+ **
+ - angle (number) angle of orientation in degrees [default: `0`]
+ - x (number) x coordinate of the blob's tail [default: Element's `x` or `cx`]
+ - y (number) y coordinate of the blob's tail [default: Element's `x` or `cx`]
+ **
+ = (object) path element of the blob
+ \*/
+Raphael.el.blob = function (angle, x, y) {
+ var bb = this.getBBox(),
+ rad = Math.PI / 180,
+ paper = this.paper || this[0].paper,
+ p, center, size;
+
+ if (!paper) return;
+
+ switch (this.type) {
+ case 'text':
+ case 'circle':
+ case 'ellipse': center = true; break;
+ default: center = false;
+ }
+
+ p = paper.path().attr({ fill: "#000", stroke: "none" });
+ angle = (+angle + 1 ? angle : 45) + 90;
+ size = Math.min(bb.height, bb.width);
+ x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
+ y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
+
+ var w = Math.max(bb.width + size, size * 25 / 12),
+ h = Math.max(bb.height + size, size * 25 / 12),
+ x2 = x + size * Math.sin((angle - 22.5) * rad),
+ y2 = y + size * Math.cos((angle - 22.5) * rad),
+ x1 = x + size * Math.sin((angle + 22.5) * rad),
+ y1 = y + size * Math.cos((angle + 22.5) * rad),
+ dx = (x1 - x2) / 2,
+ dy = (y1 - y2) / 2,
+ rx = w / 2,
+ ry = h / 2,
+ k = -Math.sqrt(Math.abs(rx * rx * ry * ry - rx * rx * dy * dy - ry * ry * dx * dx) / (rx * rx * dy * dy + ry * ry * dx * dx)),
+ cx = k * rx * dy / ry + (x1 + x2) / 2,
+ cy = k * -ry * dx / rx + (y1 + y2) / 2;
+
+ p.attr({
+ x: cx,
+ y: cy,
+ path: [
+ "M", x, y,
+ "L", x1, y1,
+ "A", rx, ry, 0, 1, 1, x2, y2,
+ "z"
+ ].join(",")
+ });
+
+ this.translate(cx - bb.x - bb.width / 2, cy - bb.y - bb.height / 2);
+
+ return p.insertBefore(this.node ? this : this[0]);
+};
+
+/*
+ * Tooltips on Paper prototype
+ */
+/*\
+ * Paper.label
+ [ method ]
+ **
+ * Puts the given `text` into a 'label' tooltip. The text is given a default style according to @g.txtattr. See @Element.label
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the center of the label
+ - y (number) y coordinate of the center of the label
+ - text (string) text to place inside the label
+ **
+ = (object) set containing the label path and the text element
+ > Usage
+ | paper.label(50, 50, "$9.99");
+ \*/
+Raphael.fn.label = function (x, y, text) {
+ var set = this.set();
+
+ text = this.text(x, y, text).attr(Raphael.g.txtattr);
+ return set.push(text.label(), text);
+};
+
+/*\
+ * Paper.popup
+ [ method ]
+ **
+ * Puts the given `text` into a 'popup' tooltip. The text is given a default style according to @g.txtattr. See @Element.popup
+ *
+ * Note: The `dir` parameter has changed from g.Raphael 0.4.1 to 0.5. The options `0`, `1`, `2`, and `3` has been changed to `'down'`, `'left'`, `'up'`, and `'right'` respectively.
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the popup's tail
+ - y (number) y coordinate of the popup's tail
+ - text (string) text to place inside the popup
+ - dir (string) location of the text relative to the tail: `'down'`, `'left'`, `'up'` [default], or `'right'`.
+ - size (number) amount of padding around the Element [default: `5`]
+ **
+ = (object) set containing the popup path and the text element
+ > Usage
+ | paper.popup(50, 50, "$9.99", 'down');
+ \*/
+Raphael.fn.popup = function (x, y, text, dir, size) {
+ var set = this.set();
+
+ text = this.text(x, y, text).attr(Raphael.g.txtattr);
+ return set.push(text.popup(dir, size), text);
+};
+
+/*\
+ * Paper.tag
+ [ method ]
+ **
+ * Puts the given text into a 'tag' tooltip. The text is given a default style according to @g.txtattr. See @Element.tag
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the center of the tag loop
+ - y (number) y coordinate of the center of the tag loop
+ - text (string) text to place inside the tag
+ - angle (number) angle of orientation in degrees [default: `0`]
+ - r (number) radius of the loop [default: `5`]
+ **
+ = (object) set containing the tag path and the text element
+ > Usage
+ | paper.tag(50, 50, "$9.99", 60);
+ \*/
+Raphael.fn.tag = function (x, y, text, angle, r) {
+ var set = this.set();
+
+ text = this.text(x, y, text).attr(Raphael.g.txtattr);
+ return set.push(text.tag(angle, r), text);
+};
+
+/*\
+ * Paper.flag
+ [ method ]
+ **
+ * Puts the given `text` into a 'flag' tooltip. The text is given a default style according to @g.txtattr. See @Element.flag
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the flag's point
+ - y (number) y coordinate of the flag's point
+ - text (string) text to place inside the flag
+ - angle (number) angle of orientation in degrees [default: `0`]
+ **
+ = (object) set containing the flag path and the text element
+ > Usage
+ | paper.flag(50, 50, "$9.99", 60);
+ \*/
+Raphael.fn.flag = function (x, y, text, angle) {
+ var set = this.set();
+
+ text = this.text(x, y, text).attr(Raphael.g.txtattr);
+ return set.push(text.flag(angle), text);
+};
+
+/*\
+ * Paper.drop
+ [ method ]
+ **
+ * Puts the given text into a 'drop' tooltip. The text is given a default style according to @g.txtattr. See @Element.drop
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the drop's point
+ - y (number) y coordinate of the drop's point
+ - text (string) text to place inside the drop
+ - angle (number) angle of orientation in degrees [default: `0`]
+ **
+ = (object) set containing the drop path and the text element
+ > Usage
+ | paper.drop(50, 50, "$9.99", 60);
+ \*/
+Raphael.fn.drop = function (x, y, text, angle) {
+ var set = this.set();
+
+ text = this.text(x, y, text).attr(Raphael.g.txtattr);
+ return set.push(text.drop(angle), text);
+};
+
+/*\
+ * Paper.blob
+ [ method ]
+ **
+ * Puts the given text into a 'blob' tooltip. The text is given a default style according to @g.txtattr. See @Element.blob
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the blob's tail
+ - y (number) y coordinate of the blob's tail
+ - text (string) text to place inside the blob
+ - angle (number) angle of orientation in degrees [default: `0`]
+ **
+ = (object) set containing the blob path and the text element
+ > Usage
+ | paper.blob(50, 50, "$9.99", 60);
+ \*/
+Raphael.fn.blob = function (x, y, text, angle) {
+ var set = this.set();
+
+ text = this.text(x, y, text).attr(Raphael.g.txtattr);
+ return set.push(text.blob(angle), text);
+};
+
+/**
+ * Brightness functions on the Element prototype
+ */
+/*\
+ * Element.lighter
+ [ method ]
+ **
+ * Makes the context element lighter by increasing the brightness and reducing the saturation by a given factor. Can be called on Sets.
+ **
+ > Parameters
+ **
+ - times (number) adjustment factor [default: `2`]
+ **
+ = (object) Element
+ > Usage
+ | paper.circle(50, 50, 20).attr({
+ | fill: "#ff0000",
+ | stroke: "#fff",
+ | "stroke-width": 2
+ | }).lighter(6);
+ \*/
+Raphael.el.lighter = function (times) {
+ times = times || 2;
+
+ var fs = [this.attrs.fill, this.attrs.stroke];
+
+ this.fs = this.fs || [fs[0], fs[1]];
+
+ fs[0] = Raphael.rgb2hsb(Raphael.getRGB(fs[0]).hex);
+ fs[1] = Raphael.rgb2hsb(Raphael.getRGB(fs[1]).hex);
+ fs[0].b = Math.min(fs[0].b * times, 1);
+ fs[0].s = fs[0].s / times;
+ fs[1].b = Math.min(fs[1].b * times, 1);
+ fs[1].s = fs[1].s / times;
+
+ this.attr({fill: "hsb(" + [fs[0].h, fs[0].s, fs[0].b] + ")", stroke: "hsb(" + [fs[1].h, fs[1].s, fs[1].b] + ")"});
+ return this;
+};
+
+/*\
+ * Element.darker
+ [ method ]
+ **
+ * Makes the context element darker by decreasing the brightness and increasing the saturation by a given factor. Can be called on Sets.
+ **
+ > Parameters
+ **
+ - times (number) adjustment factor [default: `2`]
+ **
+ = (object) Element
+ > Usage
+ | paper.circle(50, 50, 20).attr({
+ | fill: "#ff0000",
+ | stroke: "#fff",
+ | "stroke-width": 2
+ | }).darker(6);
+ \*/
+Raphael.el.darker = function (times) {
+ times = times || 2;
+
+ var fs = [this.attrs.fill, this.attrs.stroke];
+
+ this.fs = this.fs || [fs[0], fs[1]];
+
+ fs[0] = Raphael.rgb2hsb(Raphael.getRGB(fs[0]).hex);
+ fs[1] = Raphael.rgb2hsb(Raphael.getRGB(fs[1]).hex);
+ fs[0].s = Math.min(fs[0].s * times, 1);
+ fs[0].b = fs[0].b / times;
+ fs[1].s = Math.min(fs[1].s * times, 1);
+ fs[1].b = fs[1].b / times;
+
+ this.attr({fill: "hsb(" + [fs[0].h, fs[0].s, fs[0].b] + ")", stroke: "hsb(" + [fs[1].h, fs[1].s, fs[1].b] + ")"});
+ return this;
+};
+
+/*\
+ * Element.resetBrightness
+ [ method ]
+ **
+ * Resets brightness and saturation levels to their original values. See @Element.lighter and @Element.darker. Can be called on Sets.
+ **
+ = (object) Element
+ > Usage
+ | paper.circle(50, 50, 20).attr({
+ | fill: "#ff0000",
+ | stroke: "#fff",
+ | "stroke-width": 2
+ | }).lighter(6).resetBrightness();
+ \*/
+Raphael.el.resetBrightness = function () {
+ if (this.fs) {
+ this.attr({ fill: this.fs[0], stroke: this.fs[1] });
+ delete this.fs;
+ }
+ return this;
+};
+
+//alias to set prototype
+(function () {
+ var brightness = ['lighter', 'darker', 'resetBrightness'],
+ tooltips = ['popup', 'tag', 'flag', 'label', 'drop', 'blob'];
+
+ for (var f in tooltips) (function (name) {
+ Raphael.st[name] = function () {
+ return Raphael.el[name].apply(this, arguments);
+ };
+ })(tooltips[f]);
+
+ for (var f in brightness) (function (name) {
+ Raphael.st[name] = function () {
+ for (var i = 0; i < this.length; i++) {
+ this[i][name].apply(this[i], arguments);
+ }
+
+ return this;
+ };
+ })(brightness[f]);
+})();
+
+//chart prototype for storing common functions
+Raphael.g = {
+ /*\
+ * g.shim
+ [ object ]
+ **
+ * An attribute object that charts will set on all generated shims (shims being the invisible objects that mouse events are bound to)
+ **
+ > Default value
+ | { stroke: 'none', fill: '#000', 'fill-opacity': 0 }
+ \*/
+ shim: { stroke: 'none', fill: '#000', 'fill-opacity': 0 },
+
+ /*\
+ * g.txtattr
+ [ object ]
+ **
+ * An attribute object that charts and tooltips will set on any generated text
+ **
+ > Default value
+ | { font: '12px Arial, sans-serif', fill: '#fff' }
+ \*/
+ txtattr: { font: '12px Arial, sans-serif', fill: '#fff' },
+
+ /*\
+ * g.colors
+ [ array ]
+ **
+ * An array of color values that charts will iterate through when drawing chart data values.
+ **
+ \*/
+ colors: (function () {
+ var hues = [.6, .2, .05, .1333, .75, 0],
+ colors = [];
+
+ for (var i = 0; i < 10; i++) {
+ if (i < hues.length) {
+ colors.push('hsb(' + hues[i] + ',.75, .75)');
+ } else {
+ colors.push('hsb(' + hues[i - hues.length] + ', 1, .5)');
+ }
+ }
+
+ return colors;
+ })(),
+
+ snapEnds: function(from, to, steps) {
+ var f = from,
+ t = to;
+
+ if (f == t) {
+ return {from: f, to: t, power: 0};
+ }
+
+ function round(a) {
+ return Math.abs(a - .5) < .25 ? ~~(a) + .5 : Math.round(a);
+ }
+
+ var d = (t - f) / steps,
+ r = ~~(d),
+ R = r,
+ i = 0;
+
+ if (r) {
+ while (R) {
+ i--;
+ R = ~~(d * Math.pow(10, i)) / Math.pow(10, i);
+ }
+
+ i ++;
+ } else {
+ if(d == 0 || !isFinite(d)) {
+ i = 1;
+ } else {
+ while (!r) {
+ i = i || 1;
+ r = ~~(d * Math.pow(10, i)) / Math.pow(10, i);
+ i++;
+ }
+ }
+
+ i && i--;
+ }
+
+ t = round(to * Math.pow(10, i)) / Math.pow(10, i);
+
+ if (t < to) {
+ t = round((to + .5) * Math.pow(10, i)) / Math.pow(10, i);
+ }
+
+ f = round((from - (i > 0 ? 0 : .5)) * Math.pow(10, i)) / Math.pow(10, i);
+ return { from: f, to: t, power: i };
+ },
+
+ axis: function (x, y, length, from, to, steps, orientation, labels, type, dashsize, paper) {
+ dashsize = dashsize == null ? 2 : dashsize;
+ type = type || "t";
+ steps = steps || 10;
+ paper = arguments[arguments.length-1] //paper is always last argument
+
+ var path = type == "|" || type == " " ? ["M", x + .5, y, "l", 0, .001] : orientation == 1 || orientation == 3 ? ["M", x + .5, y, "l", 0, -length] : ["M", x, y + .5, "l", length, 0],
+ ends = this.snapEnds(from, to, steps),
+ f = ends.from,
+ t = ends.to,
+ i = ends.power,
+ j = 0,
+ txtattr = { font: "11px 'Fontin Sans', Fontin-Sans, sans-serif" },
+ text = paper.set(),
+ d;
+
+ d = (t - f) / steps;
+
+ var label = f,
+ rnd = i > 0 ? i : 0;
+ dx = length / steps;
+
+ if (+orientation == 1 || +orientation == 3) {
+ var Y = y,
+ addon = (orientation - 1 ? 1 : -1) * (dashsize + 3 + !!(orientation - 1));
+
+ while (Y >= y - length) {
+ type != "-" && type != " " && (path = path.concat(["M", x - (type == "+" || type == "|" ? dashsize : !(orientation - 1) * dashsize * 2), Y + .5, "l", dashsize * 2 + 1, 0]));
+ text.push(paper.text(x + addon, Y, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr).attr({ "text-anchor": orientation - 1 ? "start" : "end" }));
+ label += d;
+ Y -= dx;
+ }
+
+ if (Math.round(Y + dx - (y - length))) {
+ type != "-" && type != " " && (path = path.concat(["M", x - (type == "+" || type == "|" ? dashsize : !(orientation - 1) * dashsize * 2), y - length + .5, "l", dashsize * 2 + 1, 0]));
+ text.push(paper.text(x + addon, y - length, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr).attr({ "text-anchor": orientation - 1 ? "start" : "end" }));
+ }
+ } else {
+ label = f;
+ rnd = (i > 0) * i;
+ addon = (orientation ? -1 : 1) * (dashsize + 9 + !orientation);
+
+ var X = x,
+ dx = length / steps,
+ txt = 0,
+ prev = 0;
+
+ while (X <= x + length) {
+ type != "-" && type != " " && (path = path.concat(["M", X + .5, y - (type == "+" ? dashsize : !!orientation * dashsize * 2), "l", 0, dashsize * 2 + 1]));
+ text.push(txt = paper.text(X, y + addon, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr));
+
+ var bb = txt.getBBox();
+
+ if (prev >= bb.x - 5) {
+ text.pop(text.length - 1).remove();
+ } else {
+ prev = bb.x + bb.width;
+ }
+
+ label += d;
+ X += dx;
+ }
+
+ if (Math.round(X - dx - x - length)) {
+ type != "-" && type != " " && (path = path.concat(["M", x + length + .5, y - (type == "+" ? dashsize : !!orientation * dashsize * 2), "l", 0, dashsize * 2 + 1]));
+ text.push(paper.text(x + length, y + addon, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr));
+ }
+ }
+
+ var res = paper.path(path);
+
+ res.text = text;
+ res.all = paper.set([res, text]);
+ res.remove = function () {
+ this.text.remove();
+ this.constructor.prototype.remove.call(this);
+ };
+
+ return res;
+ },
+
+ labelise: function(label, val, total) {
+ if (label) {
+ return (label + "").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g, function (all, value, percent) {
+ if (value) {
+ return (+val).toFixed(value.replace(/^#+\.?/g, "").length);
+ }
+ if (percent) {
+ return (val * 100 / total).toFixed(percent.replace(/^%+\.?/g, "").length) + "%";
+ }
+ });
+ } else {
+ return (+val).toFixed(0);
+ }
+ }
+}
diff --git a/vendor/assets/javascripts/jquery.nicescroll.js b/vendor/assets/javascripts/jquery.nicescroll.js
new file mode 100644
index 00000000000..7653f25df4b
--- /dev/null
+++ b/vendor/assets/javascripts/jquery.nicescroll.js
@@ -0,0 +1,3634 @@
+/* jquery.nicescroll
+-- version 3.6.0
+-- copyright 2014-11-21 InuYaksa*2014
+-- licensed under the MIT
+--
+-- http://nicescroll.areaaperta.com/
+-- https://github.com/inuyaksa/jquery.nicescroll
+--
+*/
+
+(function(factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as anonymous module.
+ define(['jquery'], factory);
+ } else {
+ // Browser globals.
+ factory(jQuery);
+ }
+}(function(jQuery) {
+ "use strict";
+
+ // globals
+ var domfocus = false;
+ var mousefocus = false;
+ var tabindexcounter = 0;
+ var ascrailcounter = 2000;
+ var globalmaxzindex = 0;
+
+ var $ = jQuery; // sandbox
+
+ // http://stackoverflow.com/questions/2161159/get-script-path
+ function getScriptPath() {
+ var scripts = document.getElementsByTagName('script');
+ var path = scripts[scripts.length - 1].src.split('?')[0];
+ return (path.split('/').length > 0) ? path.split('/').slice(0, -1).join('/') + '/' : '';
+ }
+
+ var vendors = ['webkit','ms','moz','o'];
+
+ var setAnimationFrame = window.requestAnimationFrame || false;
+ var clearAnimationFrame = window.cancelAnimationFrame || false;
+
+ if (!setAnimationFrame) { // legacy detection
+ for (var vx in vendors) {
+ var v = vendors[vx];
+ if (!setAnimationFrame) setAnimationFrame = window[v + 'RequestAnimationFrame'];
+ if (!clearAnimationFrame) clearAnimationFrame = window[v + 'CancelAnimationFrame'] || window[v + 'CancelRequestAnimationFrame'];
+ }
+ }
+
+ var ClsMutationObserver = window.MutationObserver || window.WebKitMutationObserver || false;
+
+ var _globaloptions = {
+ zindex: "auto",
+ cursoropacitymin: 0,
+ cursoropacitymax: 1,
+ cursorcolor: "#424242",
+ cursorwidth: "5px",
+ cursorborder: "1px solid #fff",
+ cursorborderradius: "5px",
+ scrollspeed: 60,
+ mousescrollstep: 8 * 3,
+ touchbehavior: false,
+ hwacceleration: true,
+ usetransition: true,
+ boxzoom: false,
+ dblclickzoom: true,
+ gesturezoom: true,
+ grabcursorenabled: true,
+ autohidemode: true,
+ background: "",
+ iframeautoresize: true,
+ cursorminheight: 32,
+ preservenativescrolling: true,
+ railoffset: false,
+ railhoffset: false,
+ bouncescroll: true,
+ spacebarenabled: true,
+ railpadding: {
+ top: 0,
+ right: 0,
+ left: 0,
+ bottom: 0
+ },
+ disableoutline: true,
+ horizrailenabled: true,
+ railalign: "right",
+ railvalign: "bottom",
+ enabletranslate3d: true,
+ enablemousewheel: true,
+ enablekeyboard: true,
+ smoothscroll: true,
+ sensitiverail: true,
+ enablemouselockapi: true,
+ // cursormaxheight:false,
+ cursorfixedheight: false,
+ directionlockdeadzone: 6,
+ hidecursordelay: 400,
+ nativeparentscrolling: true,
+ enablescrollonselection: true,
+ overflowx: true,
+ overflowy: true,
+ cursordragspeed: 0.3,
+ rtlmode: "auto",
+ cursordragontouch: false,
+ oneaxismousemode: "auto",
+ scriptpath: getScriptPath(),
+ preventmultitouchscrolling: true
+ };
+
+ var browserdetected = false;
+
+ var getBrowserDetection = function() {
+
+ if (browserdetected) return browserdetected;
+
+ var _el = document.createElement('DIV'),
+ _style = _el.style,
+ _agent = navigator.userAgent,
+ _platform = navigator.platform,
+ d = {};
+
+ d.haspointerlock = "pointerLockElement" in document || "webkitPointerLockElement" in document || "mozPointerLockElement" in document;
+
+ d.isopera = ("opera" in window); // 12-
+ d.isopera12 = (d.isopera && ("getUserMedia" in navigator));
+ d.isoperamini = (Object.prototype.toString.call(window.operamini) === "[object OperaMini]");
+
+ d.isie = (("all" in document) && ("attachEvent" in _el) && !d.isopera); //IE10-
+ d.isieold = (d.isie && !("msInterpolationMode" in _style)); // IE6 and older
+ d.isie7 = d.isie && !d.isieold && (!("documentMode" in document) || (document.documentMode == 7));
+ d.isie8 = d.isie && ("documentMode" in document) && (document.documentMode == 8);
+ d.isie9 = d.isie && ("performance" in window) && (document.documentMode >= 9);
+ d.isie10 = d.isie && ("performance" in window) && (document.documentMode == 10);
+ d.isie11 = ("msRequestFullscreen" in _el) && (document.documentMode >= 11); // IE11+
+
+ d.isie9mobile = /iemobile.9/i.test(_agent); //wp 7.1 mango
+ if (d.isie9mobile) d.isie9 = false;
+ d.isie7mobile = (!d.isie9mobile && d.isie7) && /iemobile/i.test(_agent); //wp 7.0
+
+ d.ismozilla = ("MozAppearance" in _style);
+
+ d.iswebkit = ("WebkitAppearance" in _style);
+
+ d.ischrome = ("chrome" in window);
+ d.ischrome22 = (d.ischrome && d.haspointerlock);
+ d.ischrome26 = (d.ischrome && ("transition" in _style)); // issue with transform detection (maintain prefix)
+
+ d.cantouch = ("ontouchstart" in document.documentElement) || ("ontouchstart" in window); // detection for Chrome Touch Emulation
+ d.hasmstouch = (window.MSPointerEvent || false); // IE10 pointer events
+ d.hasw3ctouch = (window.PointerEvent || false); //IE11 pointer events, following W3C Pointer Events spec
+
+ d.ismac = /^mac$/i.test(_platform);
+
+ d.isios = (d.cantouch && /iphone|ipad|ipod/i.test(_platform));
+ d.isios4 = ((d.isios) && !("seal" in Object));
+ d.isios7 = ((d.isios)&&("webkitHidden" in document)); //iOS 7+
+
+ d.isandroid = (/android/i.test(_agent));
+
+ d.haseventlistener = ("addEventListener" in _el);
+
+ d.trstyle = false;
+ d.hastransform = false;
+ d.hastranslate3d = false;
+ d.transitionstyle = false;
+ d.hastransition = false;
+ d.transitionend = false;
+
+ var a;
+ var check = ['transform', 'msTransform', 'webkitTransform', 'MozTransform', 'OTransform'];
+ for (a = 0; a < check.length; a++) {
+ if (typeof _style[check[a]] != "undefined") {
+ d.trstyle = check[a];
+ break;
+ }
+ }
+ d.hastransform = (!!d.trstyle);
+ if (d.hastransform) {
+ _style[d.trstyle] = "translate3d(1px,2px,3px)";
+ d.hastranslate3d = /translate3d/.test(_style[d.trstyle]);
+ }
+
+ d.transitionstyle = false;
+ d.prefixstyle = '';
+ d.transitionend = false;
+ check = ['transition', 'webkitTransition', 'msTransition', 'MozTransition', 'OTransition', 'OTransition', 'KhtmlTransition'];
+ var prefix = ['', '-webkit-', '-ms-', '-moz-', '-o-', '-o', '-khtml-'];
+ var evs = ['transitionend', 'webkitTransitionEnd', 'msTransitionEnd', 'transitionend', 'otransitionend', 'oTransitionEnd', 'KhtmlTransitionEnd'];
+ for (a = 0; a < check.length; a++) {
+ if (check[a] in _style) {
+ d.transitionstyle = check[a];
+ d.prefixstyle = prefix[a];
+ d.transitionend = evs[a];
+ break;
+ }
+ }
+ if (d.ischrome26) { // always use prefix
+ d.prefixstyle = prefix[1];
+ }
+
+ d.hastransition = (d.transitionstyle);
+
+ function detectCursorGrab() {
+ var lst = ['-webkit-grab', '-moz-grab', 'grab'];
+ if ((d.ischrome && !d.ischrome22) || d.isie) lst = []; // force setting for IE returns false positive and chrome cursor bug
+ for (var a = 0; a < lst.length; a++) {
+ var p = lst[a];
+ _style.cursor = p;
+ if (_style.cursor == p) return p;
+ }
+ return 'url(//mail.google.com/mail/images/2/openhand.cur),n-resize'; // thank you google for custom cursor!
+ }
+ d.cursorgrabvalue = detectCursorGrab();
+
+ d.hasmousecapture = ("setCapture" in _el);
+
+ d.hasMutationObserver = (ClsMutationObserver !== false);
+
+ _el = null; //memory released
+
+ browserdetected = d;
+
+ return d;
+ };
+
+ var NiceScrollClass = function(myopt, me) {
+
+ var self = this;
+
+ this.version = '3.6.0';
+ this.name = 'nicescroll';
+
+ this.me = me;
+
+ this.opt = {
+ doc: $("body"),
+ win: false
+ };
+
+ $.extend(this.opt, _globaloptions); // clone opts
+
+ // Options for internal use
+ this.opt.snapbackspeed = 80;
+
+ if (myopt || false) {
+ for (var a in self.opt) {
+ if (typeof myopt[a] != "undefined") self.opt[a] = myopt[a];
+ }
+ }
+
+ this.doc = self.opt.doc;
+ this.iddoc = (this.doc && this.doc[0]) ? this.doc[0].id || '' : '';
+ this.ispage = /^BODY|HTML/.test((self.opt.win) ? self.opt.win[0].nodeName : this.doc[0].nodeName);
+ this.haswrapper = (self.opt.win !== false);
+ this.win = self.opt.win || (this.ispage ? $(window) : this.doc);
+ this.docscroll = (this.ispage && !this.haswrapper) ? $(window) : this.win;
+ this.body = $("body");
+ this.viewport = false;
+
+ this.isfixed = false;
+
+ this.iframe = false;
+ this.isiframe = ((this.doc[0].nodeName == 'IFRAME') && (this.win[0].nodeName == 'IFRAME'));
+
+ this.istextarea = (this.win[0].nodeName == 'TEXTAREA');
+
+ this.forcescreen = false; //force to use screen position on events
+
+ this.canshowonmouseevent = (self.opt.autohidemode != "scroll");
+
+ // Events jump table
+ this.onmousedown = false;
+ this.onmouseup = false;
+ this.onmousemove = false;
+ this.onmousewheel = false;
+ this.onkeypress = false;
+ this.ongesturezoom = false;
+ this.onclick = false;
+
+ // Nicescroll custom events
+ this.onscrollstart = false;
+ this.onscrollend = false;
+ this.onscrollcancel = false;
+
+ this.onzoomin = false;
+ this.onzoomout = false;
+
+ // Let's start!
+ this.view = false;
+ this.page = false;
+
+ this.scroll = {
+ x: 0,
+ y: 0
+ };
+ this.scrollratio = {
+ x: 0,
+ y: 0
+ };
+ this.cursorheight = 20;
+ this.scrollvaluemax = 0;
+
+ this.isrtlmode = (this.opt.rtlmode == "auto") ? ((this.win[0] == window ? this.body : this.win).css("direction") == "rtl") : (this.opt.rtlmode === true);
+ // this.checkrtlmode = false;
+
+ this.scrollrunning = false;
+
+ this.scrollmom = false;
+
+ this.observer = false; // observer div changes
+ this.observerremover = false; // observer on parent for remove detection
+ this.observerbody = false; // observer on body for position change
+
+ do {
+ this.id = "ascrail" + (ascrailcounter++);
+ } while (document.getElementById(this.id));
+
+ this.rail = false;
+ this.cursor = false;
+ this.cursorfreezed = false;
+ this.selectiondrag = false;
+
+ this.zoom = false;
+ this.zoomactive = false;
+
+ this.hasfocus = false;
+ this.hasmousefocus = false;
+
+ this.visibility = true;
+ this.railslocked = false; // locked by resize
+ this.locked = false; // prevent lost of locked status sets by user
+ this.hidden = false; // rails always hidden
+ this.cursoractive = true; // user can interact with cursors
+
+ this.wheelprevented = false; //prevent mousewheel event
+
+ this.overflowx = self.opt.overflowx;
+ this.overflowy = self.opt.overflowy;
+
+ this.nativescrollingarea = false;
+ this.checkarea = 0;
+
+ this.events = []; // event list for unbind
+
+ this.saved = {}; // style saved
+
+ this.delaylist = {};
+ this.synclist = {};
+
+ this.lastdeltax = 0;
+ this.lastdeltay = 0;
+
+ this.detected = getBrowserDetection();
+
+ var cap = $.extend({}, this.detected);
+
+ this.canhwscroll = (cap.hastransform && self.opt.hwacceleration);
+ this.ishwscroll = (this.canhwscroll && self.haswrapper);
+
+ this.hasreversehr = (this.isrtlmode&&!cap.iswebkit); //RTL mode with reverse horizontal axis
+
+ this.istouchcapable = false; // desktop devices with touch screen support
+
+ //## Check WebKit-based desktop with touch support
+ //## + Firefox 18 nightly build (desktop) false positive (or desktop with touch support)
+ if (cap.cantouch && !cap.isios && !cap.isandroid && (cap.iswebkit || cap.ismozilla)) {
+ this.istouchcapable = true;
+ cap.cantouch = false; // parse normal desktop events
+ }
+
+ //## disable MouseLock API on user request
+ if (!self.opt.enablemouselockapi) {
+ cap.hasmousecapture = false;
+ cap.haspointerlock = false;
+ }
+
+/* deprecated
+ this.delayed = function(name, fn, tm, lazy) {
+ };
+*/
+
+ this.debounced = function(name, fn, tm) {
+ var dd = self.delaylist[name];
+ self.delaylist[name] = fn;
+ if (!dd) {
+ setTimeout(function() {
+ var fn = self.delaylist[name];
+ self.delaylist[name] = false;
+ fn.call(self);
+ }, tm);
+ }
+ };
+
+ var _onsync = false;
+
+ this.synched = function(name, fn) {
+
+ function requestSync() {
+ if (_onsync) return;
+ setAnimationFrame(function() {
+ _onsync = false;
+ for (var nn in self.synclist) {
+ var fn = self.synclist[nn];
+ if (fn) fn.call(self);
+ self.synclist[nn] = false;
+ }
+ });
+ _onsync = true;
+ }
+
+ self.synclist[name] = fn;
+ requestSync();
+ return name;
+ };
+
+ this.unsynched = function(name) {
+ if (self.synclist[name]) self.synclist[name] = false;
+ };
+
+ this.css = function(el, pars) { // save & set
+ for (var n in pars) {
+ self.saved.css.push([el, n, el.css(n)]);
+ el.css(n, pars[n]);
+ }
+ };
+
+ this.scrollTop = function(val) {
+ return (typeof val == "undefined") ? self.getScrollTop() : self.setScrollTop(val);
+ };
+
+ this.scrollLeft = function(val) {
+ return (typeof val == "undefined") ? self.getScrollLeft() : self.setScrollLeft(val);
+ };
+
+ // derived by by Dan Pupius www.pupius.net
+ var BezierClass = function(st, ed, spd, p1, p2, p3, p4) {
+
+ this.st = st;
+ this.ed = ed;
+ this.spd = spd;
+
+ this.p1 = p1 || 0;
+ this.p2 = p2 || 1;
+ this.p3 = p3 || 0;
+ this.p4 = p4 || 1;
+
+ this.ts = (new Date()).getTime();
+ this.df = this.ed - this.st;
+ };
+ BezierClass.prototype = {
+ B2: function(t) {
+ return 3 * t * t * (1 - t);
+ },
+ B3: function(t) {
+ return 3 * t * (1 - t) * (1 - t);
+ },
+ B4: function(t) {
+ return (1 - t) * (1 - t) * (1 - t);
+ },
+ getNow: function() {
+ var nw = (new Date()).getTime();
+ var pc = 1 - ((nw - this.ts) / this.spd);
+ var bz = this.B2(pc) + this.B3(pc) + this.B4(pc);
+ return (pc < 0) ? this.ed : this.st + Math.round(this.df * bz);
+ },
+ update: function(ed, spd) {
+ this.st = this.getNow();
+ this.ed = ed;
+ this.spd = spd;
+ this.ts = (new Date()).getTime();
+ this.df = this.ed - this.st;
+ return this;
+ }
+ };
+
+ //derived from http://stackoverflow.com/questions/11236090/
+ function getMatrixValues() {
+ var tr = self.doc.css(cap.trstyle);
+ if (tr && (tr.substr(0, 6) == "matrix")) {
+ return tr.replace(/^.*\((.*)\)$/g, "$1").replace(/px/g, '').split(/, +/);
+ }
+ return false;
+ }
+
+ if (this.ishwscroll) {
+ // hw accelerated scroll
+ this.doc.translate = {
+ x: 0,
+ y: 0,
+ tx: "0px",
+ ty: "0px"
+ };
+
+ //this one can help to enable hw accel on ios6 http://indiegamr.com/ios6-html-hardware-acceleration-changes-and-how-to-fix-them/
+ if (cap.hastranslate3d && cap.isios) this.doc.css("-webkit-backface-visibility", "hidden"); // prevent flickering http://stackoverflow.com/questions/3461441/
+
+ this.getScrollTop = function(last) {
+ if (!last) {
+ var mtx = getMatrixValues();
+ if (mtx) return (mtx.length == 16) ? -mtx[13] : -mtx[5]; //matrix3d 16 on IE10
+ if (self.timerscroll && self.timerscroll.bz) return self.timerscroll.bz.getNow();
+ }
+ return self.doc.translate.y;
+ };
+
+ this.getScrollLeft = function(last) {
+ if (!last) {
+ var mtx = getMatrixValues();
+ if (mtx) return (mtx.length == 16) ? -mtx[12] : -mtx[4]; //matrix3d 16 on IE10
+ if (self.timerscroll && self.timerscroll.bh) return self.timerscroll.bh.getNow();
+ }
+ return self.doc.translate.x;
+ };
+
+ this.notifyScrollEvent = function(el) {
+ var e = document.createEvent("UIEvents");
+ e.initUIEvent("scroll", false, true, window, 1);
+ e.niceevent = true;
+ el.dispatchEvent(e);
+ };
+
+ var cxscrollleft = (this.isrtlmode) ? 1 : -1;
+
+ if (cap.hastranslate3d && self.opt.enabletranslate3d) {
+ this.setScrollTop = function(val, silent) {
+ self.doc.translate.y = val;
+ self.doc.translate.ty = (val * -1) + "px";
+ self.doc.css(cap.trstyle, "translate3d(" + self.doc.translate.tx + "," + self.doc.translate.ty + ",0px)");
+ if (!silent) self.notifyScrollEvent(self.win[0]);
+ };
+ this.setScrollLeft = function(val, silent) {
+ self.doc.translate.x = val;
+ self.doc.translate.tx = (val * cxscrollleft) + "px";
+ self.doc.css(cap.trstyle, "translate3d(" + self.doc.translate.tx + "," + self.doc.translate.ty + ",0px)");
+ if (!silent) self.notifyScrollEvent(self.win[0]);
+ };
+ } else {
+ this.setScrollTop = function(val, silent) {
+ self.doc.translate.y = val;
+ self.doc.translate.ty = (val * -1) + "px";
+ self.doc.css(cap.trstyle, "translate(" + self.doc.translate.tx + "," + self.doc.translate.ty + ")");
+ if (!silent) self.notifyScrollEvent(self.win[0]);
+ };
+ this.setScrollLeft = function(val, silent) {
+ self.doc.translate.x = val;
+ self.doc.translate.tx = (val * cxscrollleft) + "px";
+ self.doc.css(cap.trstyle, "translate(" + self.doc.translate.tx + "," + self.doc.translate.ty + ")");
+ if (!silent) self.notifyScrollEvent(self.win[0]);
+ };
+ }
+ } else {
+ // native scroll
+ this.getScrollTop = function() {
+ return self.docscroll.scrollTop();
+ };
+ this.setScrollTop = function(val) {
+ return self.docscroll.scrollTop(val);
+ };
+ this.getScrollLeft = function() {
+ if (self.detected.ismozilla && self.isrtlmode)
+ return Math.abs(self.docscroll.scrollLeft());
+ return self.docscroll.scrollLeft();
+ };
+ this.setScrollLeft = function(val) {
+ return self.docscroll.scrollLeft((self.detected.ismozilla && self.isrtlmode) ? -val : val);
+ };
+ }
+
+ this.getTarget = function(e) {
+ if (!e) return false;
+ if (e.target) return e.target;
+ if (e.srcElement) return e.srcElement;
+ return false;
+ };
+
+ this.hasParent = function(e, id) {
+ if (!e) return false;
+ var el = e.target || e.srcElement || e || false;
+ while (el && el.id != id) {
+ el = el.parentNode || false;
+ }
+ return (el !== false);
+ };
+
+ function getZIndex() {
+ var dom = self.win;
+ if ("zIndex" in dom) return dom.zIndex(); // use jQuery UI method when available
+ while (dom.length > 0) {
+ if (dom[0].nodeType == 9) return false;
+ var zi = dom.css('zIndex');
+ if (!isNaN(zi) && zi != 0) return parseInt(zi);
+ dom = dom.parent();
+ }
+ return false;
+ }
+
+ //inspired by http://forum.jquery.com/topic/width-includes-border-width-when-set-to-thin-medium-thick-in-ie
+ var _convertBorderWidth = {
+ "thin": 1,
+ "medium": 3,
+ "thick": 5
+ };
+
+ function getWidthToPixel(dom, prop, chkheight) {
+ var wd = dom.css(prop);
+ var px = parseFloat(wd);
+ if (isNaN(px)) {
+ px = _convertBorderWidth[wd] || 0;
+ var brd = (px == 3) ? ((chkheight) ? (self.win.outerHeight() - self.win.innerHeight()) : (self.win.outerWidth() - self.win.innerWidth())) : 1; //DON'T TRUST CSS
+ if (self.isie8 && px) px += 1;
+ return (brd) ? px : 0;
+ }
+ return px;
+ }
+
+ this.getDocumentScrollOffset = function() {
+ return {top:window.pageYOffset||document.documentElement.scrollTop,
+ left:window.pageXOffset||document.documentElement.scrollLeft};
+ }
+
+ this.getOffset = function() {
+ if (self.isfixed) {
+ var ofs = self.win.offset(); // fix Chrome auto issue (when right/bottom props only)
+ var scrl = self.getDocumentScrollOffset();
+ ofs.top-=scrl.top;
+ ofs.left-=scrl.left;
+ return ofs;
+ }
+ var ww = self.win.offset();
+ if (!self.viewport) return ww;
+ var vp = self.viewport.offset();
+ return {
+ top: ww.top - vp.top,// + self.viewport.scrollTop(),
+ left: ww.left - vp.left // + self.viewport.scrollLeft()
+ };
+ };
+
+ this.updateScrollBar = function(len) {
+ if (self.ishwscroll) {
+ self.rail.css({ //**
+ height: self.win.innerHeight() - (self.opt.railpadding.top + self.opt.railpadding.bottom)
+ });
+ if (self.railh) self.railh.css({ //**
+ width: self.win.innerWidth() - (self.opt.railpadding.left + self.opt.railpadding.right)
+ });
+
+ } else {
+ var wpos = self.getOffset();
+ var pos = {
+ top: wpos.top,
+ left: wpos.left - (self.opt.railpadding.left + self.opt.railpadding.right)
+ };
+ pos.top += getWidthToPixel(self.win, 'border-top-width', true);
+ pos.left += (self.rail.align) ? self.win.outerWidth() - getWidthToPixel(self.win, 'border-right-width') - self.rail.width : getWidthToPixel(self.win, 'border-left-width');
+
+ var off = self.opt.railoffset;
+ if (off) {
+ if (off.top) pos.top += off.top;
+ if (self.rail.align && off.left) pos.left += off.left;
+ }
+
+ if (!self.railslocked) self.rail.css({
+ top: pos.top,
+ left: pos.left,
+ height: ((len) ? len.h : self.win.innerHeight()) - (self.opt.railpadding.top + self.opt.railpadding.bottom)
+ });
+
+ if (self.zoom) {
+ self.zoom.css({
+ top: pos.top + 1,
+ left: (self.rail.align == 1) ? pos.left - 20 : pos.left + self.rail.width + 4
+ });
+ }
+
+ if (self.railh && !self.railslocked) {
+ var pos = {
+ top: wpos.top,
+ left: wpos.left
+ };
+ var off = self.opt.railhoffset;
+ if (!!off) {
+ if (!!off.top) pos.top += off.top;
+ if (!!off.left) pos.left += off.left;
+ }
+ var y = (self.railh.align) ? pos.top + getWidthToPixel(self.win, 'border-top-width', true) + self.win.innerHeight() - self.railh.height : pos.top + getWidthToPixel(self.win, 'border-top-width', true);
+ var x = pos.left + getWidthToPixel(self.win, 'border-left-width');
+ self.railh.css({
+ top: y - (self.opt.railpadding.top + self.opt.railpadding.bottom),
+ left: x,
+ width: self.railh.width
+ });
+ }
+
+
+ }
+ };
+
+ this.doRailClick = function(e, dbl, hr) {
+ var fn, pg, cur, pos;
+
+ if (self.railslocked) return;
+ self.cancelEvent(e);
+
+ if (dbl) {
+ fn = (hr) ? self.doScrollLeft : self.doScrollTop;
+ cur = (hr) ? ((e.pageX - self.railh.offset().left - (self.cursorwidth / 2)) * self.scrollratio.x) : ((e.pageY - self.rail.offset().top - (self.cursorheight / 2)) * self.scrollratio.y);
+ fn(cur);
+ } else {
+ fn = (hr) ? self.doScrollLeftBy : self.doScrollBy;
+ cur = (hr) ? self.scroll.x : self.scroll.y;
+ pos = (hr) ? e.pageX - self.railh.offset().left : e.pageY - self.rail.offset().top;
+ pg = (hr) ? self.view.w : self.view.h;
+ fn((cur >= pos) ? pg: -pg);// (cur >= pos) ? fn(pg): fn(-pg);
+ }
+
+ };
+
+ self.hasanimationframe = (setAnimationFrame);
+ self.hascancelanimationframe = (clearAnimationFrame);
+
+ if (!self.hasanimationframe) {
+ setAnimationFrame = function(fn) {
+ return setTimeout(fn, 15 - Math.floor((+new Date()) / 1000) % 16);
+ }; // 1000/60)};
+ clearAnimationFrame = clearInterval;
+ } else if (!self.hascancelanimationframe) clearAnimationFrame = function() {
+ self.cancelAnimationFrame = true;
+ };
+
+ this.init = function() {
+
+ self.saved.css = [];
+
+ if (cap.isie7mobile) return true; // SORRY, DO NOT WORK!
+ if (cap.isoperamini) return true; // SORRY, DO NOT WORK!
+
+ if (cap.hasmstouch) self.css((self.ispage) ? $("html") : self.win, {
+ '-ms-touch-action': 'none'
+ });
+
+ self.zindex = "auto";
+ if (!self.ispage && self.opt.zindex == "auto") {
+ self.zindex = getZIndex() || "auto";
+ } else {
+ self.zindex = self.opt.zindex;
+ }
+
+ if (!self.ispage && self.zindex != "auto") {
+ if (self.zindex > globalmaxzindex) globalmaxzindex = self.zindex;
+ }
+
+ if (self.isie && self.zindex == 0 && self.opt.zindex == "auto") { // fix IE auto == 0
+ self.zindex = "auto";
+ }
+
+ if (!self.ispage || (!cap.cantouch && !cap.isieold && !cap.isie9mobile)) {
+
+ var cont = self.docscroll;
+ if (self.ispage) cont = (self.haswrapper) ? self.win : self.doc;
+
+ if (!cap.isie9mobile) self.css(cont, {
+ 'overflow-y': 'hidden'
+ });
+
+ if (self.ispage && cap.isie7) {
+ if (self.doc[0].nodeName == 'BODY') self.css($("html"), {
+ 'overflow-y': 'hidden'
+ }); //IE7 double scrollbar issue
+ else if (self.doc[0].nodeName == 'HTML') self.css($("body"), {
+ 'overflow-y': 'hidden'
+ }); //IE7 double scrollbar issue
+ }
+
+ if (cap.isios && !self.ispage && !self.haswrapper) self.css($("body"), {
+ "-webkit-overflow-scrolling": "touch"
+ }); //force hw acceleration
+
+ var cursor = $(document.createElement('div'));
+ cursor.css({
+ position: "relative",
+ top: 0,
+ "float": "right",
+ width: self.opt.cursorwidth,
+ height: "0px",
+ 'background-color': self.opt.cursorcolor,
+ border: self.opt.cursorborder,
+ 'background-clip': 'padding-box',
+ '-webkit-border-radius': self.opt.cursorborderradius,
+ '-moz-border-radius': self.opt.cursorborderradius,
+ 'border-radius': self.opt.cursorborderradius
+ });
+
+ cursor.hborder = parseFloat(cursor.outerHeight() - cursor.innerHeight());
+
+ cursor.addClass('nicescroll-cursors');
+
+ self.cursor = cursor;
+
+ var rail = $(document.createElement('div'));
+ rail.attr('id', self.id);
+ rail.addClass('nicescroll-rails nicescroll-rails-vr');
+
+ var v, a, kp = ["left","right","top","bottom"]; //**
+ for (var n in kp) {
+ a = kp[n];
+ v = self.opt.railpadding[a];
+ (v) ? rail.css("padding-"+a,v+"px") : self.opt.railpadding[a] = 0;
+ }
+
+ rail.append(cursor);
+
+ rail.width = Math.max(parseFloat(self.opt.cursorwidth), cursor.outerWidth());
+ rail.css({
+ width: rail.width + "px",
+ 'zIndex': self.zindex,
+ "background": self.opt.background,
+ cursor: "default"
+ });
+
+ rail.visibility = true;
+ rail.scrollable = true;
+
+ rail.align = (self.opt.railalign == "left") ? 0 : 1;
+
+ self.rail = rail;
+
+ self.rail.drag = false;
+
+ var zoom = false;
+ if (self.opt.boxzoom && !self.ispage && !cap.isieold) {
+ zoom = document.createElement('div');
+
+ self.bind(zoom, "click", self.doZoom);
+ self.bind(zoom, "mouseenter", function() {
+ self.zoom.css('opacity', self.opt.cursoropacitymax);
+ });
+ self.bind(zoom, "mouseleave", function() {
+ self.zoom.css('opacity', self.opt.cursoropacitymin);
+ });
+
+ self.zoom = $(zoom);
+ self.zoom.css({
+ "cursor": "pointer",
+ 'z-index': self.zindex,
+ 'backgroundImage': 'url(' + self.opt.scriptpath + 'zoomico.png)',
+ 'height': 18,
+ 'width': 18,
+ 'backgroundPosition': '0px 0px'
+ });
+ if (self.opt.dblclickzoom) self.bind(self.win, "dblclick", self.doZoom);
+ if (cap.cantouch && self.opt.gesturezoom) {
+ self.ongesturezoom = function(e) {
+ if (e.scale > 1.5) self.doZoomIn(e);
+ if (e.scale < 0.8) self.doZoomOut(e);
+ return self.cancelEvent(e);
+ };
+ self.bind(self.win, "gestureend", self.ongesturezoom);
+ }
+ }
+
+ // init HORIZ
+
+ self.railh = false;
+ var railh;
+
+ if (self.opt.horizrailenabled) {
+
+ self.css(cont, {
+ 'overflow-x': 'hidden'
+ });
+
+ var cursor = $(document.createElement('div'));
+ cursor.css({
+ position: "absolute",
+ top: 0,
+ height: self.opt.cursorwidth,
+ width: "0px",
+ 'background-color': self.opt.cursorcolor,
+ border: self.opt.cursorborder,
+ 'background-clip': 'padding-box',
+ '-webkit-border-radius': self.opt.cursorborderradius,
+ '-moz-border-radius': self.opt.cursorborderradius,
+ 'border-radius': self.opt.cursorborderradius
+ });
+
+ if (cap.isieold) cursor.css({'overflow':'hidden'}); //IE6 horiz scrollbar issue
+
+ cursor.wborder = parseFloat(cursor.outerWidth() - cursor.innerWidth());
+
+ cursor.addClass('nicescroll-cursors');
+
+ self.cursorh = cursor;
+
+ railh = $(document.createElement('div'));
+ railh.attr('id', self.id + '-hr');
+ railh.addClass('nicescroll-rails nicescroll-rails-hr');
+ railh.height = Math.max(parseFloat(self.opt.cursorwidth), cursor.outerHeight());
+ railh.css({
+ height: railh.height + "px",
+ 'zIndex': self.zindex,
+ "background": self.opt.background
+ });
+
+ railh.append(cursor);
+
+ railh.visibility = true;
+ railh.scrollable = true;
+
+ railh.align = (self.opt.railvalign == "top") ? 0 : 1;
+
+ self.railh = railh;
+
+ self.railh.drag = false;
+
+ }
+
+ //
+
+ if (self.ispage) {
+ rail.css({
+ position: "fixed",
+ top: "0px",
+ height: "100%"
+ });
+ (rail.align) ? rail.css({
+ right: "0px"
+ }): rail.css({
+ left: "0px"
+ });
+ self.body.append(rail);
+ if (self.railh) {
+ railh.css({
+ position: "fixed",
+ left: "0px",
+ width: "100%"
+ });
+ (railh.align) ? railh.css({
+ bottom: "0px"
+ }): railh.css({
+ top: "0px"
+ });
+ self.body.append(railh);
+ }
+ } else {
+ if (self.ishwscroll) {
+ if (self.win.css('position') == 'static') self.css(self.win, {
+ 'position': 'relative'
+ });
+ var bd = (self.win[0].nodeName == 'HTML') ? self.body : self.win;
+ $(bd).scrollTop(0).scrollLeft(0); // fix rail position if content already scrolled
+ if (self.zoom) {
+ self.zoom.css({
+ position: "absolute",
+ top: 1,
+ right: 0,
+ "margin-right": rail.width + 4
+ });
+ bd.append(self.zoom);
+ }
+ rail.css({
+ position: "absolute",
+ top: 0
+ });
+ (rail.align) ? rail.css({
+ right: 0
+ }): rail.css({
+ left: 0
+ });
+ bd.append(rail);
+ if (railh) {
+ railh.css({
+ position: "absolute",
+ left: 0,
+ bottom: 0
+ });
+ (railh.align) ? railh.css({
+ bottom: 0
+ }): railh.css({
+ top: 0
+ });
+ bd.append(railh);
+ }
+ } else {
+ self.isfixed = (self.win.css("position") == "fixed");
+ var rlpos = (self.isfixed) ? "fixed" : "absolute";
+
+ if (!self.isfixed) self.viewport = self.getViewport(self.win[0]);
+ if (self.viewport) {
+ self.body = self.viewport;
+ if ((/fixed|absolute/.test(self.viewport.css("position"))) == false) self.css(self.viewport, {
+ "position": "relative"
+ });
+ }
+
+ rail.css({
+ position: rlpos
+ });
+ if (self.zoom) self.zoom.css({
+ position: rlpos
+ });
+ self.updateScrollBar();
+ self.body.append(rail);
+ if (self.zoom) self.body.append(self.zoom);
+ if (self.railh) {
+ railh.css({
+ position: rlpos
+ });
+ self.body.append(railh);
+ }
+ }
+
+ if (cap.isios) self.css(self.win, {
+ '-webkit-tap-highlight-color': 'rgba(0,0,0,0)',
+ '-webkit-touch-callout': 'none'
+ }); // prevent grey layer on click
+
+ if (cap.isie && self.opt.disableoutline) self.win.attr("hideFocus", "true"); // IE, prevent dotted rectangle on focused div
+ if (cap.iswebkit && self.opt.disableoutline) self.win.css({"outline": "none"}); // Webkit outline
+ //if (cap.isopera&&self.opt.disableoutline) self.win.css({"outline":"0"}); // Opera 12- to test [TODO]
+
+ }
+
+ if (self.opt.autohidemode === false) {
+ self.autohidedom = false;
+ self.rail.css({
+ opacity: self.opt.cursoropacitymax
+ });
+ if (self.railh) self.railh.css({
+ opacity: self.opt.cursoropacitymax
+ });
+ } else if ((self.opt.autohidemode === true) || (self.opt.autohidemode === "leave")) {
+ self.autohidedom = $().add(self.rail);
+ if (cap.isie8) self.autohidedom = self.autohidedom.add(self.cursor);
+ if (self.railh) self.autohidedom = self.autohidedom.add(self.railh);
+ if (self.railh && cap.isie8) self.autohidedom = self.autohidedom.add(self.cursorh);
+ } else if (self.opt.autohidemode == "scroll") {
+ self.autohidedom = $().add(self.rail);
+ if (self.railh) self.autohidedom = self.autohidedom.add(self.railh);
+ } else if (self.opt.autohidemode == "cursor") {
+ self.autohidedom = $().add(self.cursor);
+ if (self.railh) self.autohidedom = self.autohidedom.add(self.cursorh);
+ } else if (self.opt.autohidemode == "hidden") {
+ self.autohidedom = false;
+ self.hide();
+ self.railslocked = false;
+ }
+
+ if (cap.isie9mobile) {
+
+ self.scrollmom = new ScrollMomentumClass2D(self);
+
+ self.onmangotouch = function() {
+ var py = self.getScrollTop();
+ var px = self.getScrollLeft();
+
+ if ((py == self.scrollmom.lastscrolly) && (px == self.scrollmom.lastscrollx)) return true;
+
+ var dfy = py - self.mangotouch.sy;
+ var dfx = px - self.mangotouch.sx;
+ var df = Math.round(Math.sqrt(Math.pow(dfx, 2) + Math.pow(dfy, 2)));
+ if (df == 0) return;
+
+ var dry = (dfy < 0) ? -1 : 1;
+ var drx = (dfx < 0) ? -1 : 1;
+
+ var tm = +new Date();
+ if (self.mangotouch.lazy) clearTimeout(self.mangotouch.lazy);
+
+ if (((tm - self.mangotouch.tm) > 80) || (self.mangotouch.dry != dry) || (self.mangotouch.drx != drx)) {
+ self.scrollmom.stop();
+ self.scrollmom.reset(px, py);
+ self.mangotouch.sy = py;
+ self.mangotouch.ly = py;
+ self.mangotouch.sx = px;
+ self.mangotouch.lx = px;
+ self.mangotouch.dry = dry;
+ self.mangotouch.drx = drx;
+ self.mangotouch.tm = tm;
+ } else {
+
+ self.scrollmom.stop();
+ self.scrollmom.update(self.mangotouch.sx - dfx, self.mangotouch.sy - dfy);
+ self.mangotouch.tm = tm;
+
+ var ds = Math.max(Math.abs(self.mangotouch.ly - py), Math.abs(self.mangotouch.lx - px));
+ self.mangotouch.ly = py;
+ self.mangotouch.lx = px;
+
+ if (ds > 2) {
+ self.mangotouch.lazy = setTimeout(function() {
+ self.mangotouch.lazy = false;
+ self.mangotouch.dry = 0;
+ self.mangotouch.drx = 0;
+ self.mangotouch.tm = 0;
+ self.scrollmom.doMomentum(30);
+ }, 100);
+ }
+ }
+ };
+
+ var top = self.getScrollTop();
+ var lef = self.getScrollLeft();
+ self.mangotouch = {
+ sy: top,
+ ly: top,
+ dry: 0,
+ sx: lef,
+ lx: lef,
+ drx: 0,
+ lazy: false,
+ tm: 0
+ };
+
+ self.bind(self.docscroll, "scroll", self.onmangotouch);
+
+ } else {
+
+ if (cap.cantouch || self.istouchcapable || self.opt.touchbehavior || cap.hasmstouch) {
+
+ self.scrollmom = new ScrollMomentumClass2D(self);
+
+ self.ontouchstart = function(e) {
+ if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
+
+ self.hasmoving = false;
+
+ if (!self.railslocked) {
+
+ var tg;
+ if (cap.hasmstouch) {
+ tg = (e.target) ? e.target : false;
+ while (tg) {
+ var nc = $(tg).getNiceScroll();
+ if ((nc.length > 0) && (nc[0].me == self.me)) break;
+ if (nc.length > 0) return false;
+ if ((tg.nodeName == 'DIV') && (tg.id == self.id)) break;
+ tg = (tg.parentNode) ? tg.parentNode : false;
+ }
+ }
+
+ self.cancelScroll();
+
+ tg = self.getTarget(e);
+
+ if (tg) {
+ var skp = (/INPUT/i.test(tg.nodeName)) && (/range/i.test(tg.type));
+ if (skp) return self.stopPropagation(e);
+ }
+
+ if (!("clientX" in e) && ("changedTouches" in e)) {
+ e.clientX = e.changedTouches[0].clientX;
+ e.clientY = e.changedTouches[0].clientY;
+ }
+
+ if (self.forcescreen) {
+ var le = e;
+ e = {
+ "original": (e.original) ? e.original : e
+ };
+ e.clientX = le.screenX;
+ e.clientY = le.screenY;
+ }
+
+ self.rail.drag = {
+ x: e.clientX,
+ y: e.clientY,
+ sx: self.scroll.x,
+ sy: self.scroll.y,
+ st: self.getScrollTop(),
+ sl: self.getScrollLeft(),
+ pt: 2,
+ dl: false
+ };
+
+ if (self.ispage || !self.opt.directionlockdeadzone) {
+ self.rail.drag.dl = "f";
+ } else {
+
+ var view = {
+ w: $(window).width(),
+ h: $(window).height()
+ };
+
+ var page = {
+ w: Math.max(document.body.scrollWidth, document.documentElement.scrollWidth),
+ h: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)
+ };
+
+ var maxh = Math.max(0, page.h - view.h);
+ var maxw = Math.max(0, page.w - view.w);
+
+ if (!self.rail.scrollable && self.railh.scrollable) self.rail.drag.ck = (maxh > 0) ? "v" : false;
+ else if (self.rail.scrollable && !self.railh.scrollable) self.rail.drag.ck = (maxw > 0) ? "h" : false;
+ else self.rail.drag.ck = false;
+ if (!self.rail.drag.ck) self.rail.drag.dl = "f";
+ }
+
+ if (self.opt.touchbehavior && self.isiframe && cap.isie) {
+ var wp = self.win.position();
+ self.rail.drag.x += wp.left;
+ self.rail.drag.y += wp.top;
+ }
+
+ self.hasmoving = false;
+ self.lastmouseup = false;
+ self.scrollmom.reset(e.clientX, e.clientY);
+
+ if (!cap.cantouch && !this.istouchcapable && !e.pointerType) {
+
+ var ip = (tg) ? /INPUT|SELECT|TEXTAREA/i.test(tg.nodeName) : false;
+ if (!ip) {
+ if (!self.ispage && cap.hasmousecapture) tg.setCapture();
+ if (self.opt.touchbehavior) {
+ if (tg.onclick && !(tg._onclick || false)) { // intercept DOM0 onclick event
+ tg._onclick = tg.onclick;
+ tg.onclick = function(e) {
+ if (self.hasmoving) return false;
+ tg._onclick.call(this, e);
+ };
+ }
+ return self.cancelEvent(e);
+ }
+ return self.stopPropagation(e);
+ }
+
+ if (/SUBMIT|CANCEL|BUTTON/i.test($(tg).attr('type'))) {
+ pc = {
+ "tg": tg,
+ "click": false
+ };
+ self.preventclick = pc;
+ }
+
+ }
+ }
+
+ };
+
+ self.ontouchend = function(e) {
+ if (!self.rail.drag) return true;
+ if (self.rail.drag.pt == 2) {
+ if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
+ self.scrollmom.doMomentum();
+ self.rail.drag = false;
+ if (self.hasmoving) {
+ self.lastmouseup = true;
+ self.hideCursor();
+ if (cap.hasmousecapture) document.releaseCapture();
+ if (!cap.cantouch) return self.cancelEvent(e);
+ }
+ }
+ else if (self.rail.drag.pt == 1) {
+ return self.onmouseup(e);
+ }
+
+ };
+
+ var moveneedoffset = (self.opt.touchbehavior && self.isiframe && !cap.hasmousecapture);
+
+ self.ontouchmove = function(e, byiframe) {
+
+ if (!self.rail.drag) return false;
+
+ if (e.targetTouches && self.opt.preventmultitouchscrolling) {
+ if (e.targetTouches.length > 1) return false; // multitouch
+ }
+
+ if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
+
+ if (self.rail.drag.pt == 2) {
+ if (cap.cantouch && (cap.isios) && (typeof e.original == "undefined")) return true; // prevent ios "ghost" events by clickable elements
+
+ self.hasmoving = true;
+
+ if (self.preventclick && !self.preventclick.click) {
+ self.preventclick.click = self.preventclick.tg.onclick || false;
+ self.preventclick.tg.onclick = self.onpreventclick;
+ }
+
+ var ev = $.extend({
+ "original": e
+ }, e);
+ e = ev;
+
+ if (("changedTouches" in e)) {
+ e.clientX = e.changedTouches[0].clientX;
+ e.clientY = e.changedTouches[0].clientY;
+ }
+
+ if (self.forcescreen) {
+ var le = e;
+ e = {
+ "original": (e.original) ? e.original : e
+ };
+ e.clientX = le.screenX;
+ e.clientY = le.screenY;
+ }
+
+ var ofy,ofx;
+ ofx = ofy = 0;
+
+ if (moveneedoffset && !byiframe) {
+ var wp = self.win.position();
+ ofx = -wp.left;
+ ofy = -wp.top;
+ }
+
+ var fy = e.clientY + ofy;
+ var my = (fy - self.rail.drag.y);
+ var fx = e.clientX + ofx;
+ var mx = (fx - self.rail.drag.x);
+
+ var ny = self.rail.drag.st - my;
+
+ if (self.ishwscroll && self.opt.bouncescroll) {
+ if (ny < 0) {
+ ny = Math.round(ny / 2);
+ // fy = 0;
+ } else if (ny > self.page.maxh) {
+ ny = self.page.maxh + Math.round((ny - self.page.maxh) / 2);
+ // fy = 0;
+ }
+ } else {
+ if (ny < 0) {
+ ny = 0;
+ fy = 0;
+ }
+ if (ny > self.page.maxh) {
+ ny = self.page.maxh;
+ fy = 0;
+ }
+ }
+
+ var nx;
+ if (self.railh && self.railh.scrollable) {
+ nx = (self.isrtlmode) ? mx - self.rail.drag.sl : self.rail.drag.sl - mx;
+
+ if (self.ishwscroll && self.opt.bouncescroll) {
+ if (nx < 0) {
+ nx = Math.round(nx / 2);
+ // fx = 0;
+ } else if (nx > self.page.maxw) {
+ nx = self.page.maxw + Math.round((nx - self.page.maxw) / 2);
+ // fx = 0;
+ }
+ } else {
+ if (nx < 0) {
+ nx = 0;
+ fx = 0;
+ }
+ if (nx > self.page.maxw) {
+ nx = self.page.maxw;
+ fx = 0;
+ }
+ }
+
+ }
+
+ var grabbed = false;
+ if (self.rail.drag.dl) {
+ grabbed = true;
+ if (self.rail.drag.dl == "v") nx = self.rail.drag.sl;
+ else if (self.rail.drag.dl == "h") ny = self.rail.drag.st;
+ } else {
+ var ay = Math.abs(my);
+ var ax = Math.abs(mx);
+ var dz = self.opt.directionlockdeadzone;
+ if (self.rail.drag.ck == "v") {
+ if (ay > dz && (ax <= (ay * 0.3))) {
+ self.rail.drag = false;
+ return true;
+ } else if (ax > dz) {
+ self.rail.drag.dl = "f";
+ $("body").scrollTop($("body").scrollTop()); // stop iOS native scrolling (when active javascript has blocked)
+ }
+ } else if (self.rail.drag.ck == "h") {
+ if (ax > dz && (ay <= (ax * 0.3))) {
+ self.rail.drag = false;
+ return true;
+ } else if (ay > dz) {
+ self.rail.drag.dl = "f";
+ $("body").scrollLeft($("body").scrollLeft()); // stop iOS native scrolling (when active javascript has blocked)
+ }
+ }
+ }
+
+ self.synched("touchmove", function() {
+ if (self.rail.drag && (self.rail.drag.pt == 2)) {
+ if (self.prepareTransition) self.prepareTransition(0);
+ if (self.rail.scrollable) self.setScrollTop(ny);
+ self.scrollmom.update(fx, fy);
+ if (self.railh && self.railh.scrollable) {
+ self.setScrollLeft(nx);
+ self.showCursor(ny, nx);
+ } else {
+ self.showCursor(ny);
+ }
+ if (cap.isie10) document.selection.clear();
+ }
+ });
+
+ if (cap.ischrome && self.istouchcapable) grabbed = false; //chrome touch emulation doesn't like!
+ if (grabbed) return self.cancelEvent(e);
+ }
+ else if (self.rail.drag.pt == 1) { // drag on cursor
+ return self.onmousemove(e);
+ }
+
+ };
+
+ }
+
+ self.onmousedown = function(e, hronly) {
+ if (self.rail.drag && self.rail.drag.pt != 1) return;
+ if (self.railslocked) return self.cancelEvent(e);
+ self.cancelScroll();
+ self.rail.drag = {
+ x: e.clientX,
+ y: e.clientY,
+ sx: self.scroll.x,
+ sy: self.scroll.y,
+ pt: 1,
+ hr: (!!hronly)
+ };
+ var tg = self.getTarget(e);
+ if (!self.ispage && cap.hasmousecapture) tg.setCapture();
+ if (self.isiframe && !cap.hasmousecapture) {
+ self.saved.csspointerevents = self.doc.css("pointer-events");
+ self.css(self.doc, {
+ "pointer-events": "none"
+ });
+ }
+ self.hasmoving = false;
+ return self.cancelEvent(e);
+ };
+
+ self.onmouseup = function(e) {
+ if (self.rail.drag) {
+ if (self.rail.drag.pt != 1) return true;
+ if (cap.hasmousecapture) document.releaseCapture();
+ if (self.isiframe && !cap.hasmousecapture) self.doc.css("pointer-events", self.saved.csspointerevents);
+ self.rail.drag = false;
+ //if (!self.rail.active) self.hideCursor();
+ if (self.hasmoving) self.triggerScrollEnd(); // TODO - check &&!self.scrollrunning
+ return self.cancelEvent(e);
+ }
+ };
+
+ self.onmousemove = function(e) {
+ if (self.rail.drag) {
+ if (self.rail.drag.pt != 1) return;
+
+ if (cap.ischrome && e.which == 0) return self.onmouseup(e);
+
+ self.cursorfreezed = true;
+ self.hasmoving = true;
+
+ if (self.rail.drag.hr) {
+ self.scroll.x = self.rail.drag.sx + (e.clientX - self.rail.drag.x);
+ if (self.scroll.x < 0) self.scroll.x = 0;
+ var mw = self.scrollvaluemaxw;
+ if (self.scroll.x > mw) self.scroll.x = mw;
+ } else {
+ self.scroll.y = self.rail.drag.sy + (e.clientY - self.rail.drag.y);
+ if (self.scroll.y < 0) self.scroll.y = 0;
+ var my = self.scrollvaluemax;
+ if (self.scroll.y > my) self.scroll.y = my;
+ }
+
+ self.synched('mousemove', function() {
+ if (self.rail.drag && (self.rail.drag.pt == 1)) {
+ self.showCursor();
+ if (self.rail.drag.hr) {
+ if (self.hasreversehr) {
+ self.doScrollLeft(self.scrollvaluemaxw-Math.round(self.scroll.x * self.scrollratio.x), self.opt.cursordragspeed);
+ } else {
+ self.doScrollLeft(Math.round(self.scroll.x * self.scrollratio.x), self.opt.cursordragspeed);
+ }
+ }
+ else self.doScrollTop(Math.round(self.scroll.y * self.scrollratio.y), self.opt.cursordragspeed);
+ }
+ });
+
+ return self.cancelEvent(e);
+ }
+ /*
+ else {
+ self.checkarea = true;
+ }
+*/
+ };
+
+ if (cap.cantouch || self.opt.touchbehavior) {
+
+ self.onpreventclick = function(e) {
+ if (self.preventclick) {
+ self.preventclick.tg.onclick = self.preventclick.click;
+ self.preventclick = false;
+ return self.cancelEvent(e);
+ }
+ }
+
+ self.bind(self.win, "mousedown", self.ontouchstart); // control content dragging
+
+ self.onclick = (cap.isios) ? false : function(e) {
+ if (self.lastmouseup) {
+ self.lastmouseup = false;
+ return self.cancelEvent(e);
+ } else {
+ return true;
+ }
+ };
+
+ if (self.opt.grabcursorenabled && cap.cursorgrabvalue) {
+ self.css((self.ispage) ? self.doc : self.win, {
+ 'cursor': cap.cursorgrabvalue
+ });
+ self.css(self.rail, {
+ 'cursor': cap.cursorgrabvalue
+ });
+ }
+
+ } else {
+
+ var checkSelectionScroll = function(e) {
+ if (!self.selectiondrag) return;
+
+ if (e) {
+ var ww = self.win.outerHeight();
+ var df = (e.pageY - self.selectiondrag.top);
+ if (df > 0 && df < ww) df = 0;
+ if (df >= ww) df -= ww;
+ self.selectiondrag.df = df;
+ }
+ if (self.selectiondrag.df == 0) return;
+
+ var rt = -Math.floor(self.selectiondrag.df / 6) * 2;
+ self.doScrollBy(rt);
+
+ self.debounced("doselectionscroll", function() {
+ checkSelectionScroll()
+ }, 50);
+ };
+
+ if ("getSelection" in document) { // A grade - Major browsers
+ self.hasTextSelected = function() {
+ return (document.getSelection().rangeCount > 0);
+ };
+ } else if ("selection" in document) { //IE9-
+ self.hasTextSelected = function() {
+ return (document.selection.type != "None");
+ };
+ } else {
+ self.hasTextSelected = function() { // no support
+ return false;
+ };
+ }
+
+ self.onselectionstart = function(e) {
+/* More testing - severe chrome issues
+ if (!self.haswrapper&&(e.which&&e.which==2)) { // fool browser to manage middle button scrolling
+ self.win.css({'overflow':'auto'});
+ setTimeout(function(){
+ self.win.css({'overflow':''});
+ },10);
+ return true;
+ }
+*/
+ if (self.ispage) return;
+ self.selectiondrag = self.win.offset();
+ };
+
+ self.onselectionend = function(e) {
+ self.selectiondrag = false;
+ };
+ self.onselectiondrag = function(e) {
+ if (!self.selectiondrag) return;
+ if (self.hasTextSelected()) self.debounced("selectionscroll", function() {
+ checkSelectionScroll(e)
+ }, 250);
+ };
+
+
+ }
+
+ if (cap.hasw3ctouch) { //IE11+
+ self.css(self.rail, {
+ 'touch-action': 'none'
+ });
+ self.css(self.cursor, {
+ 'touch-action': 'none'
+ });
+ self.bind(self.win, "pointerdown", self.ontouchstart);
+ self.bind(document, "pointerup", self.ontouchend);
+ self.bind(document, "pointermove", self.ontouchmove);
+ } else if (cap.hasmstouch) { //IE10
+ self.css(self.rail, {
+ '-ms-touch-action': 'none'
+ });
+ self.css(self.cursor, {
+ '-ms-touch-action': 'none'
+ });
+ self.bind(self.win, "MSPointerDown", self.ontouchstart);
+ self.bind(document, "MSPointerUp", self.ontouchend);
+ self.bind(document, "MSPointerMove", self.ontouchmove);
+ self.bind(self.cursor, "MSGestureHold", function(e) {
+ e.preventDefault()
+ });
+ self.bind(self.cursor, "contextmenu", function(e) {
+ e.preventDefault()
+ });
+ } else if (this.istouchcapable) { //desktop with screen touch enabled
+ self.bind(self.win, "touchstart", self.ontouchstart);
+ self.bind(document, "touchend", self.ontouchend);
+ self.bind(document, "touchcancel", self.ontouchend);
+ self.bind(document, "touchmove", self.ontouchmove);
+ }
+
+
+ if (self.opt.cursordragontouch || (!cap.cantouch && !self.opt.touchbehavior)) {
+
+ self.rail.css({
+ "cursor": "default"
+ });
+ self.railh && self.railh.css({
+ "cursor": "default"
+ });
+
+ self.jqbind(self.rail, "mouseenter", function() {
+ if (!self.ispage && !self.win.is(":visible")) return false;
+ if (self.canshowonmouseevent) self.showCursor();
+ self.rail.active = true;
+ });
+ self.jqbind(self.rail, "mouseleave", function() {
+ self.rail.active = false;
+ if (!self.rail.drag) self.hideCursor();
+ });
+
+ if (self.opt.sensitiverail) {
+ self.bind(self.rail, "click", function(e) {
+ self.doRailClick(e, false, false)
+ });
+ self.bind(self.rail, "dblclick", function(e) {
+ self.doRailClick(e, true, false)
+ });
+ self.bind(self.cursor, "click", function(e) {
+ self.cancelEvent(e)
+ });
+ self.bind(self.cursor, "dblclick", function(e) {
+ self.cancelEvent(e)
+ });
+ }
+
+ if (self.railh) {
+ self.jqbind(self.railh, "mouseenter", function() {
+ if (!self.ispage && !self.win.is(":visible")) return false;
+ if (self.canshowonmouseevent) self.showCursor();
+ self.rail.active = true;
+ });
+ self.jqbind(self.railh, "mouseleave", function() {
+ self.rail.active = false;
+ if (!self.rail.drag) self.hideCursor();
+ });
+
+ if (self.opt.sensitiverail) {
+ self.bind(self.railh, "click", function(e) {
+ self.doRailClick(e, false, true)
+ });
+ self.bind(self.railh, "dblclick", function(e) {
+ self.doRailClick(e, true, true)
+ });
+ self.bind(self.cursorh, "click", function(e) {
+ self.cancelEvent(e)
+ });
+ self.bind(self.cursorh, "dblclick", function(e) {
+ self.cancelEvent(e)
+ });
+ }
+
+ }
+
+ }
+
+ if (!cap.cantouch && !self.opt.touchbehavior) {
+
+ self.bind((cap.hasmousecapture) ? self.win : document, "mouseup", self.onmouseup);
+ self.bind(document, "mousemove", self.onmousemove);
+ if (self.onclick) self.bind(document, "click", self.onclick);
+
+ self.bind(self.cursor, "mousedown", self.onmousedown);
+ self.bind(self.cursor, "mouseup", self.onmouseup);
+
+ if (self.railh) {
+ self.bind(self.cursorh, "mousedown", function(e) {
+ self.onmousedown(e, true)
+ });
+ self.bind(self.cursorh, "mouseup", self.onmouseup);
+ }
+
+ if (!self.ispage && self.opt.enablescrollonselection) {
+ self.bind(self.win[0], "mousedown", self.onselectionstart);
+ self.bind(document, "mouseup", self.onselectionend);
+ self.bind(self.cursor, "mouseup", self.onselectionend);
+ if (self.cursorh) self.bind(self.cursorh, "mouseup", self.onselectionend);
+ self.bind(document, "mousemove", self.onselectiondrag);
+ }
+
+ if (self.zoom) {
+ self.jqbind(self.zoom, "mouseenter", function() {
+ if (self.canshowonmouseevent) self.showCursor();
+ self.rail.active = true;
+ });
+ self.jqbind(self.zoom, "mouseleave", function() {
+ self.rail.active = false;
+ if (!self.rail.drag) self.hideCursor();
+ });
+ }
+
+ } else {
+
+ self.bind((cap.hasmousecapture) ? self.win : document, "mouseup", self.ontouchend);
+ self.bind(document, "mousemove", self.ontouchmove);
+ if (self.onclick) self.bind(document, "click", self.onclick);
+
+ if (self.opt.cursordragontouch) {
+ self.bind(self.cursor, "mousedown", self.onmousedown);
+ self.bind(self.cursor, "mouseup", self.onmouseup);
+ //self.bind(self.cursor, "mousemove", self.onmousemove);
+ self.cursorh && self.bind(self.cursorh, "mousedown", function(e) {
+ self.onmousedown(e, true)
+ });
+ //self.cursorh && self.bind(self.cursorh, "mousemove", self.onmousemove);
+ self.cursorh && self.bind(self.cursorh, "mouseup", self.onmouseup);
+ }
+
+ }
+
+ if (self.opt.enablemousewheel) {
+ if (!self.isiframe) self.bind((cap.isie && self.ispage) ? document : self.win /*self.docscroll*/ , "mousewheel", self.onmousewheel);
+ self.bind(self.rail, "mousewheel", self.onmousewheel);
+ if (self.railh) self.bind(self.railh, "mousewheel", self.onmousewheelhr);
+ }
+
+ if (!self.ispage && !cap.cantouch && !(/HTML|^BODY/.test(self.win[0].nodeName))) {
+ if (!self.win.attr("tabindex")) self.win.attr({
+ "tabindex": tabindexcounter++
+ });
+
+ self.jqbind(self.win, "focus", function(e) {
+ domfocus = (self.getTarget(e)).id || true;
+ self.hasfocus = true;
+ if (self.canshowonmouseevent) self.noticeCursor();
+ });
+ self.jqbind(self.win, "blur", function(e) {
+ domfocus = false;
+ self.hasfocus = false;
+ });
+
+ self.jqbind(self.win, "mouseenter", function(e) {
+ mousefocus = (self.getTarget(e)).id || true;
+ self.hasmousefocus = true;
+ if (self.canshowonmouseevent) self.noticeCursor();
+ });
+ self.jqbind(self.win, "mouseleave", function() {
+ mousefocus = false;
+ self.hasmousefocus = false;
+ if (!self.rail.drag) self.hideCursor();
+ });
+
+ }
+
+ } // !ie9mobile
+
+ //Thanks to http://www.quirksmode.org !!
+ self.onkeypress = function(e) {
+ if (self.railslocked && self.page.maxh == 0) return true;
+
+ e = (e) ? e : window.e;
+ var tg = self.getTarget(e);
+ if (tg && /INPUT|TEXTAREA|SELECT|OPTION/.test(tg.nodeName)) {
+ var tp = tg.getAttribute('type') || tg.type || false;
+ if ((!tp) || !(/submit|button|cancel/i.tp)) return true;
+ }
+
+ if ($(tg).attr('contenteditable')) return true;
+
+ if (self.hasfocus || (self.hasmousefocus && !domfocus) || (self.ispage && !domfocus && !mousefocus)) {
+ var key = e.keyCode;
+
+ if (self.railslocked && key != 27) return self.cancelEvent(e);
+
+ var ctrl = e.ctrlKey || false;
+ var shift = e.shiftKey || false;
+
+ var ret = false;
+ switch (key) {
+ case 38:
+ case 63233: //safari
+ self.doScrollBy(24 * 3);
+ ret = true;
+ break;
+ case 40:
+ case 63235: //safari
+ self.doScrollBy(-24 * 3);
+ ret = true;
+ break;
+ case 37:
+ case 63232: //safari
+ if (self.railh) {
+ (ctrl) ? self.doScrollLeft(0): self.doScrollLeftBy(24 * 3);
+ ret = true;
+ }
+ break;
+ case 39:
+ case 63234: //safari
+ if (self.railh) {
+ (ctrl) ? self.doScrollLeft(self.page.maxw): self.doScrollLeftBy(-24 * 3);
+ ret = true;
+ }
+ break;
+ case 33:
+ case 63276: // safari
+ self.doScrollBy(self.view.h);
+ ret = true;
+ break;
+ case 34:
+ case 63277: // safari
+ self.doScrollBy(-self.view.h);
+ ret = true;
+ break;
+ case 36:
+ case 63273: // safari
+ (self.railh && ctrl) ? self.doScrollPos(0, 0): self.doScrollTo(0);
+ ret = true;
+ break;
+ case 35:
+ case 63275: // safari
+ (self.railh && ctrl) ? self.doScrollPos(self.page.maxw, self.page.maxh): self.doScrollTo(self.page.maxh);
+ ret = true;
+ break;
+ case 32:
+ if (self.opt.spacebarenabled) {
+ (shift) ? self.doScrollBy(self.view.h): self.doScrollBy(-self.view.h);
+ ret = true;
+ }
+ break;
+ case 27: // ESC
+ if (self.zoomactive) {
+ self.doZoom();
+ ret = true;
+ }
+ break;
+ }
+ if (ret) return self.cancelEvent(e);
+ }
+ };
+
+ if (self.opt.enablekeyboard) self.bind(document, (cap.isopera && !cap.isopera12) ? "keypress" : "keydown", self.onkeypress);
+
+ self.bind(document, "keydown", function(e) {
+ var ctrl = e.ctrlKey || false;
+ if (ctrl) self.wheelprevented = true;
+ });
+ self.bind(document, "keyup", function(e) {
+ var ctrl = e.ctrlKey || false;
+ if (!ctrl) self.wheelprevented = false;
+ });
+ self.bind(window,"blur",function(e){
+ self.wheelprevented = false;
+ });
+
+ self.bind(window, 'resize', self.lazyResize);
+ self.bind(window, 'orientationchange', self.lazyResize);
+
+ self.bind(window, "load", self.lazyResize);
+
+ if (cap.ischrome && !self.ispage && !self.haswrapper) { //chrome void scrollbar bug - it persists in version 26
+ var tmp = self.win.attr("style");
+ var ww = parseFloat(self.win.css("width")) + 1;
+ self.win.css('width', ww);
+ self.synched("chromefix", function() {
+ self.win.attr("style", tmp)
+ });
+ }
+
+
+ // Trying a cross-browser implementation - good luck!
+
+ self.onAttributeChange = function(e) {
+ self.lazyResize(self.isieold ? 250 : 30);
+ };
+
+ if (ClsMutationObserver !== false) {
+ self.observerbody = new ClsMutationObserver(function(mutations) {
+ mutations.forEach(function(mut){
+ if (mut.type=="attributes") {
+ return ($("body").hasClass("modal-open")) ? self.hide() : self.show(); // Support for Bootstrap modal
+ }
+ });
+ if (document.body.scrollHeight!=self.page.maxh) return self.lazyResize(30);
+ });
+ self.observerbody.observe(document.body, {
+ childList: true,
+ subtree: true,
+ characterData: false,
+ attributes: true,
+ attributeFilter: ['class']
+ });
+ }
+
+ if (!self.ispage && !self.haswrapper) {
+ // redesigned MutationObserver for Chrome18+/Firefox14+/iOS6+ with support for: remove div, add/remove content
+ if (ClsMutationObserver !== false) {
+ self.observer = new ClsMutationObserver(function(mutations) {
+ mutations.forEach(self.onAttributeChange);
+ });
+ self.observer.observe(self.win[0], {
+ childList: true,
+ characterData: false,
+ attributes: true,
+ subtree: false
+ });
+ self.observerremover = new ClsMutationObserver(function(mutations) {
+ mutations.forEach(function(mo) {
+ if (mo.removedNodes.length > 0) {
+ for (var dd in mo.removedNodes) {
+ if (!!self && (mo.removedNodes[dd] == self.win[0])) return self.remove();
+ }
+ }
+ });
+ });
+ self.observerremover.observe(self.win[0].parentNode, {
+ childList: true,
+ characterData: false,
+ attributes: false,
+ subtree: false
+ });
+ } else {
+ self.bind(self.win, (cap.isie && !cap.isie9) ? "propertychange" : "DOMAttrModified", self.onAttributeChange);
+ if (cap.isie9) self.win[0].attachEvent("onpropertychange", self.onAttributeChange); //IE9 DOMAttrModified bug
+ self.bind(self.win, "DOMNodeRemoved", function(e) {
+ if (e.target == self.win[0]) self.remove();
+ });
+ }
+ }
+
+ //
+
+ if (!self.ispage && self.opt.boxzoom) self.bind(window, "resize", self.resizeZoom);
+ if (self.istextarea) self.bind(self.win, "mouseup", self.lazyResize);
+
+ // self.checkrtlmode = true;
+ self.lazyResize(30);
+
+ }
+
+ if (this.doc[0].nodeName == 'IFRAME') {
+ var oniframeload = function() {
+ self.iframexd = false;
+ var doc;
+ try {
+ doc = 'contentDocument' in this ? this.contentDocument : this.contentWindow.document;
+ var a = doc.domain;
+ } catch (e) {
+ self.iframexd = true;
+ doc = false
+ }
+
+ if (self.iframexd) {
+ if ("console" in window) console.log('NiceScroll error: policy restriced iframe');
+ return true; //cross-domain - I can't manage this
+ }
+
+ self.forcescreen = true;
+
+ if (self.isiframe) {
+ self.iframe = {
+ "doc": $(doc),
+ "html": self.doc.contents().find('html')[0],
+ "body": self.doc.contents().find('body')[0]
+ };
+ self.getContentSize = function() {
+ return {
+ w: Math.max(self.iframe.html.scrollWidth, self.iframe.body.scrollWidth),
+ h: Math.max(self.iframe.html.scrollHeight, self.iframe.body.scrollHeight)
+ };
+ };
+ self.docscroll = $(self.iframe.body); //$(this.contentWindow);
+ }
+
+ if (!cap.isios && self.opt.iframeautoresize && !self.isiframe) {
+ self.win.scrollTop(0); // reset position
+ self.doc.height(""); //reset height to fix browser bug
+ var hh = Math.max(doc.getElementsByTagName('html')[0].scrollHeight, doc.body.scrollHeight);
+ self.doc.height(hh);
+ }
+ self.lazyResize(30);
+
+ if (cap.isie7) self.css($(self.iframe.html), {
+ 'overflow-y': 'hidden'
+ });
+ self.css($(self.iframe.body), {
+ 'overflow-y': 'hidden'
+ });
+
+ if (cap.isios && self.haswrapper) {
+ self.css($(doc.body), {
+ '-webkit-transform': 'translate3d(0,0,0)'
+ }); // avoid iFrame content clipping - thanks to http://blog.derraab.com/2012/04/02/avoid-iframe-content-clipping-with-css-transform-on-ios/
+ }
+
+ if ('contentWindow' in this) {
+ self.bind(this.contentWindow, "scroll", self.onscroll); //IE8 & minor
+ } else {
+ self.bind(doc, "scroll", self.onscroll);
+ }
+
+ if (self.opt.enablemousewheel) {
+ self.bind(doc, "mousewheel", self.onmousewheel);
+ }
+
+ if (self.opt.enablekeyboard) self.bind(doc, (cap.isopera) ? "keypress" : "keydown", self.onkeypress);
+
+ if (cap.cantouch || self.opt.touchbehavior) {
+ self.bind(doc, "mousedown", self.ontouchstart);
+ self.bind(doc, "mousemove", function(e) {
+ return self.ontouchmove(e, true)
+ });
+ if (self.opt.grabcursorenabled && cap.cursorgrabvalue) self.css($(doc.body), {
+ 'cursor': cap.cursorgrabvalue
+ });
+ }
+
+ self.bind(doc, "mouseup", self.ontouchend);
+
+ if (self.zoom) {
+ if (self.opt.dblclickzoom) self.bind(doc, 'dblclick', self.doZoom);
+ if (self.ongesturezoom) self.bind(doc, "gestureend", self.ongesturezoom);
+ }
+ };
+
+ if (this.doc[0].readyState && this.doc[0].readyState == "complete") {
+ setTimeout(function() {
+ oniframeload.call(self.doc[0], false)
+ }, 500);
+ }
+ self.bind(this.doc, "load", oniframeload);
+
+ }
+
+ };
+
+ this.showCursor = function(py, px) {
+ if (self.cursortimeout) {
+ clearTimeout(self.cursortimeout);
+ self.cursortimeout = 0;
+ }
+ if (!self.rail) return;
+ if (self.autohidedom) {
+ self.autohidedom.stop().css({
+ opacity: self.opt.cursoropacitymax
+ });
+ self.cursoractive = true;
+ }
+
+ if (!self.rail.drag || self.rail.drag.pt != 1) {
+ if ((typeof py != "undefined") && (py !== false)) {
+ self.scroll.y = Math.round(py * 1 / self.scrollratio.y);
+ }
+ if (typeof px != "undefined") {
+ self.scroll.x = Math.round(px * 1 / self.scrollratio.x);
+ }
+ }
+
+ self.cursor.css({
+ height: self.cursorheight,
+ top: self.scroll.y
+ });
+ if (self.cursorh) {
+ var lx = (self.hasreversehr) ? self.scrollvaluemaxw-self.scroll.x : self.scroll.x;
+ (!self.rail.align && self.rail.visibility) ? self.cursorh.css({
+ width: self.cursorwidth,
+ left: lx + self.rail.width
+ }): self.cursorh.css({
+ width: self.cursorwidth,
+ left: lx
+ });
+ self.cursoractive = true;
+ }
+
+ if (self.zoom) self.zoom.stop().css({
+ opacity: self.opt.cursoropacitymax
+ });
+ };
+
+ this.hideCursor = function(tm) {
+ if (self.cursortimeout) return;
+ if (!self.rail) return;
+ if (!self.autohidedom) return;
+ if (self.hasmousefocus && self.opt.autohidemode == "leave") return;
+ self.cursortimeout = setTimeout(function() {
+ if (!self.rail.active || !self.showonmouseevent) {
+ self.autohidedom.stop().animate({
+ opacity: self.opt.cursoropacitymin
+ });
+ if (self.zoom) self.zoom.stop().animate({
+ opacity: self.opt.cursoropacitymin
+ });
+ self.cursoractive = false;
+ }
+ self.cursortimeout = 0;
+ }, tm || self.opt.hidecursordelay);
+ };
+
+ this.noticeCursor = function(tm, py, px) {
+ self.showCursor(py, px);
+ if (!self.rail.active) self.hideCursor(tm);
+ };
+
+ this.getContentSize =
+ (self.ispage) ?
+ function() {
+ return {
+ w: Math.max(document.body.scrollWidth, document.documentElement.scrollWidth),
+ h: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)
+ }
+ } : (self.haswrapper) ?
+ function() {
+ return {
+ w: self.doc.outerWidth() + parseInt(self.win.css('paddingLeft')) + parseInt(self.win.css('paddingRight')),
+ h: self.doc.outerHeight() + parseInt(self.win.css('paddingTop')) + parseInt(self.win.css('paddingBottom'))
+ }
+ } : function() {
+ return {
+ w: self.docscroll[0].scrollWidth,
+ h: self.docscroll[0].scrollHeight
+ }
+ };
+
+ this.onResize = function(e, page) {
+
+ if (!self || !self.win) return false;
+
+ if (!self.haswrapper && !self.ispage) {
+ if (self.win.css('display') == 'none') {
+ if (self.visibility) self.hideRail().hideRailHr();
+ return false;
+ } else {
+ if (!self.hidden && !self.visibility) self.showRail().showRailHr();
+ }
+ }
+
+ var premaxh = self.page.maxh;
+ var premaxw = self.page.maxw;
+
+ var preview = {
+ h: self.view.h,
+ w: self.view.w
+ };
+
+ self.view = {
+ w: (self.ispage) ? self.win.width() : parseInt(self.win[0].clientWidth),
+ h: (self.ispage) ? self.win.height() : parseInt(self.win[0].clientHeight)
+ };
+
+ self.page = (page) ? page : self.getContentSize();
+
+ self.page.maxh = Math.max(0, self.page.h - self.view.h);
+ self.page.maxw = Math.max(0, self.page.w - self.view.w);
+
+ if ((self.page.maxh == premaxh) && (self.page.maxw == premaxw) && (self.view.w == preview.w) && (self.view.h == preview.h)) {
+ // test position
+ if (!self.ispage) {
+ var pos = self.win.offset();
+ if (self.lastposition) {
+ var lst = self.lastposition;
+ if ((lst.top == pos.top) && (lst.left == pos.left)) return self; //nothing to do
+ }
+ self.lastposition = pos;
+ } else {
+ return self; //nothing to do
+ }
+ }
+
+ if (self.page.maxh == 0) {
+ self.hideRail();
+ self.scrollvaluemax = 0;
+ self.scroll.y = 0;
+ self.scrollratio.y = 0;
+ self.cursorheight = 0;
+ self.setScrollTop(0);
+ self.rail.scrollable = false;
+ } else {
+ self.page.maxh -= (self.opt.railpadding.top + self.opt.railpadding.bottom); //**
+ self.rail.scrollable = true;
+ }
+
+ if (self.page.maxw == 0) {
+ self.hideRailHr();
+ self.scrollvaluemaxw = 0;
+ self.scroll.x = 0;
+ self.scrollratio.x = 0;
+ self.cursorwidth = 0;
+ self.setScrollLeft(0);
+ self.railh.scrollable = false;
+ } else {
+ self.page.maxw -= (self.opt.railpadding.left + self.opt.railpadding.right); //**
+ self.railh.scrollable = true;
+ }
+
+ self.railslocked = (self.locked) || ((self.page.maxh == 0) && (self.page.maxw == 0));
+ if (self.railslocked) {
+ if (!self.ispage) self.updateScrollBar(self.view);
+ return false;
+ }
+
+ if (!self.hidden && !self.visibility) {
+ self.showRail().showRailHr();
+ }
+ else if (!self.hidden && !self.railh.visibility) self.showRailHr();
+
+ if (self.istextarea && self.win.css('resize') && self.win.css('resize') != 'none') self.view.h -= 20;
+
+ self.cursorheight = Math.min(self.view.h, Math.round(self.view.h * (self.view.h / self.page.h)));
+ self.cursorheight = (self.opt.cursorfixedheight) ? self.opt.cursorfixedheight : Math.max(self.opt.cursorminheight, self.cursorheight);
+
+ self.cursorwidth = Math.min(self.view.w, Math.round(self.view.w * (self.view.w / self.page.w)));
+ self.cursorwidth = (self.opt.cursorfixedheight) ? self.opt.cursorfixedheight : Math.max(self.opt.cursorminheight, self.cursorwidth);
+
+ self.scrollvaluemax = self.view.h - self.cursorheight - self.cursor.hborder - (self.opt.railpadding.top + self.opt.railpadding.bottom); //**
+
+ if (self.railh) {
+ self.railh.width = (self.page.maxh > 0) ? (self.view.w - self.rail.width) : self.view.w;
+ self.scrollvaluemaxw = self.railh.width - self.cursorwidth - self.cursorh.wborder - (self.opt.railpadding.left + self.opt.railpadding.right); //**
+ }
+
+ /*
+ if (self.checkrtlmode&&self.railh) {
+ self.checkrtlmode = false;
+ if (self.opt.rtlmode&&self.scroll.x==0) self.setScrollLeft(self.page.maxw);
+ }
+*/
+
+ if (!self.ispage) self.updateScrollBar(self.view);
+
+ self.scrollratio = {
+ x: (self.page.maxw / self.scrollvaluemaxw),
+ y: (self.page.maxh / self.scrollvaluemax)
+ };
+
+ var sy = self.getScrollTop();
+ if (sy > self.page.maxh) {
+ self.doScrollTop(self.page.maxh);
+ } else {
+ self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y));
+ self.scroll.x = Math.round(self.getScrollLeft() * (1 / self.scrollratio.x));
+ if (self.cursoractive) self.noticeCursor();
+ }
+
+ if (self.scroll.y && (self.getScrollTop() == 0)) self.doScrollTo(Math.floor(self.scroll.y * self.scrollratio.y));
+
+ return self;
+ };
+
+ this.resize = self.onResize;
+
+ this.lazyResize = function(tm) { // event debounce
+ tm = (isNaN(tm)) ? 30 : tm;
+ self.debounced('resize', self.resize, tm);
+ return self;
+ };
+
+ // modified by MDN https://developer.mozilla.org/en-US/docs/DOM/Mozilla_event_reference/wheel
+ function _modernWheelEvent(dom, name, fn, bubble) {
+ self._bind(dom, name, function(e) {
+ var e = (e) ? e : window.event;
+ var event = {
+ original: e,
+ target: e.target || e.srcElement,
+ type: "wheel",
+ deltaMode: e.type == "MozMousePixelScroll" ? 0 : 1,
+ deltaX: 0,
+ deltaZ: 0,
+ preventDefault: function() {
+ e.preventDefault ? e.preventDefault() : e.returnValue = false;
+ return false;
+ },
+ stopImmediatePropagation: function() {
+ (e.stopImmediatePropagation) ? e.stopImmediatePropagation(): e.cancelBubble = true;
+ }
+ };
+
+ if (name == "mousewheel") {
+ event.deltaY = -1 / 40 * e.wheelDelta;
+ e.wheelDeltaX && (event.deltaX = -1 / 40 * e.wheelDeltaX);
+ } else {
+ event.deltaY = e.detail;
+ }
+
+ return fn.call(dom, event);
+ }, bubble);
+ };
+
+
+
+ this.jqbind = function(dom, name, fn) { // use jquery bind for non-native events (mouseenter/mouseleave)
+ self.events.push({
+ e: dom,
+ n: name,
+ f: fn,
+ q: true
+ });
+ $(dom).bind(name, fn);
+ };
+
+ this.bind = function(dom, name, fn, bubble) { // touch-oriented & fixing jquery bind
+ var el = ("jquery" in dom) ? dom[0] : dom;
+
+ if (name == 'mousewheel') {
+ if (window.addEventListener||'onwheel' in document) { // modern brosers & IE9 detection fix
+ self._bind(el, "wheel", fn, bubble || false);
+ } else {
+ var wname = (typeof document.onmousewheel != "undefined") ? "mousewheel" : "DOMMouseScroll"; // older IE/Firefox
+ _modernWheelEvent(el, wname, fn, bubble || false);
+ if (wname == "DOMMouseScroll") _modernWheelEvent(el, "MozMousePixelScroll", fn, bubble || false); // Firefox legacy
+ }
+ } else if (el.addEventListener) {
+ if (cap.cantouch && /mouseup|mousedown|mousemove/.test(name)) { // touch device support
+ var tt = (name == 'mousedown') ? 'touchstart' : (name == 'mouseup') ? 'touchend' : 'touchmove';
+ self._bind(el, tt, function(e) {
+ if (e.touches) {
+ if (e.touches.length < 2) {
+ var ev = (e.touches.length) ? e.touches[0] : e;
+ ev.original = e;
+ fn.call(this, ev);
+ }
+ } else if (e.changedTouches) {
+ var ev = e.changedTouches[0];
+ ev.original = e;
+ fn.call(this, ev);
+ } //blackberry
+ }, bubble || false);
+ }
+ self._bind(el, name, fn, bubble || false);
+ if (cap.cantouch && name == "mouseup") self._bind(el, "touchcancel", fn, bubble || false);
+ } else {
+ self._bind(el, name, function(e) {
+ e = e || window.event || false;
+ if (e) {
+ if (e.srcElement) e.target = e.srcElement;
+ }
+ if (!("pageY" in e)) {
+ e.pageX = e.clientX + document.documentElement.scrollLeft;
+ e.pageY = e.clientY + document.documentElement.scrollTop;
+ }
+ return ((fn.call(el, e) === false) || bubble === false) ? self.cancelEvent(e) : true;
+ });
+ }
+ };
+
+ if (cap.haseventlistener) { // W3C standard model
+ this._bind = function(el, name, fn, bubble) { // primitive bind
+ self.events.push({
+ e: el,
+ n: name,
+ f: fn,
+ b: bubble,
+ q: false
+ });
+ el.addEventListener(name, fn, bubble || false);
+ };
+ this.cancelEvent = function(e) {
+ if (!e) return false;
+ var e = (e.original) ? e.original : e;
+ e.preventDefault();
+ e.stopPropagation();
+ if (e.preventManipulation) e.preventManipulation(); //IE10
+ return false;
+ };
+ this.stopPropagation = function(e) {
+ if (!e) return false;
+ var e = (e.original) ? e.original : e;
+ e.stopPropagation();
+ return false;
+ };
+ this._unbind = function(el, name, fn, bub) { // primitive unbind
+ el.removeEventListener(name, fn, bub);
+ };
+ } else { // old IE model
+ this._bind = function(el, name, fn, bubble) { // primitive bind
+ self.events.push({
+ e: el,
+ n: name,
+ f: fn,
+ b: bubble,
+ q: false
+ });
+ if (el.attachEvent) {
+ el.attachEvent("on" + name, fn);
+ } else {
+ el["on" + name] = fn;
+ }
+ };
+ // Thanks to http://www.switchonthecode.com !!
+ this.cancelEvent = function(e) {
+ var e = window.event || false;
+ if (!e) return false;
+ e.cancelBubble = true;
+ e.cancel = true;
+ e.returnValue = false;
+ return false;
+ };
+ this.stopPropagation = function(e) {
+ var e = window.event || false;
+ if (!e) return false;
+ e.cancelBubble = true;
+ return false;
+ };
+ this._unbind = function(el, name, fn, bub) { // primitive unbind IE old
+ if (el.detachEvent) {
+ el.detachEvent('on' + name, fn);
+ } else {
+ el['on' + name] = false;
+ }
+ };
+ }
+
+ this.unbindAll = function() {
+ for (var a = 0; a < self.events.length; a++) {
+ var r = self.events[a];
+ (r.q) ? r.e.unbind(r.n, r.f): self._unbind(r.e, r.n, r.f, r.b);
+ }
+ };
+
+ this.showRail = function() {
+ if ((self.page.maxh != 0) && (self.ispage || self.win.css('display') != 'none')) {
+ self.visibility = true;
+ self.rail.visibility = true;
+ self.rail.css('display', 'block');
+ }
+ return self;
+ };
+
+ this.showRailHr = function() {
+ if (!self.railh) return self;
+ if ((self.page.maxw != 0) && (self.ispage || self.win.css('display') != 'none')) {
+ self.railh.visibility = true;
+ self.railh.css('display', 'block');
+ }
+ return self;
+ };
+
+ this.hideRail = function() {
+ self.visibility = false;
+ self.rail.visibility = false;
+ self.rail.css('display', 'none');
+ return self;
+ };
+
+ this.hideRailHr = function() {
+ if (!self.railh) return self;
+ self.railh.visibility = false;
+ self.railh.css('display', 'none');
+ return self;
+ };
+
+ this.show = function() {
+ self.hidden = false;
+ self.railslocked = false;
+ return self.showRail().showRailHr();
+ };
+
+ this.hide = function() {
+ self.hidden = true;
+ self.railslocked = true;
+ return self.hideRail().hideRailHr();
+ };
+
+ this.toggle = function() {
+ return (self.hidden) ? self.show() : self.hide();
+ };
+
+ this.remove = function() {
+ self.stop();
+ if (self.cursortimeout) clearTimeout(self.cursortimeout);
+ self.doZoomOut();
+ self.unbindAll();
+
+ if (cap.isie9) self.win[0].detachEvent("onpropertychange", self.onAttributeChange); //IE9 DOMAttrModified bug
+
+ if (self.observer !== false) self.observer.disconnect();
+ if (self.observerremover !== false) self.observerremover.disconnect();
+ if (self.observerbody !== false) self.observerbody.disconnect();
+
+ self.events = null;
+
+ if (self.cursor) {
+ self.cursor.remove();
+ }
+ if (self.cursorh) {
+ self.cursorh.remove();
+ }
+ if (self.rail) {
+ self.rail.remove();
+ }
+ if (self.railh) {
+ self.railh.remove();
+ }
+ if (self.zoom) {
+ self.zoom.remove();
+ }
+ for (var a = 0; a < self.saved.css.length; a++) {
+ var d = self.saved.css[a];
+ d[0].css(d[1], (typeof d[2] == "undefined") ? '' : d[2]);
+ }
+ self.saved = false;
+ self.me.data('__nicescroll', ''); //erase all traces
+
+ // memory leak fixed by GianlucaGuarini - thanks a lot!
+ // remove the current nicescroll from the $.nicescroll array & normalize array
+ var lst = $.nicescroll;
+ lst.each(function(i) {
+ if (!this) return;
+ if (this.id === self.id) {
+ delete lst[i];
+ for (var b = ++i; b < lst.length; b++, i++) lst[i] = lst[b];
+ lst.length--;
+ if (lst.length) delete lst[lst.length];
+ }
+ });
+
+ for (var i in self) {
+ self[i] = null;
+ delete self[i];
+ }
+
+ self = null;
+
+ };
+
+ this.scrollstart = function(fn) {
+ this.onscrollstart = fn;
+ return self;
+ };
+ this.scrollend = function(fn) {
+ this.onscrollend = fn;
+ return self;
+ };
+ this.scrollcancel = function(fn) {
+ this.onscrollcancel = fn;
+ return self;
+ };
+
+ this.zoomin = function(fn) {
+ this.onzoomin = fn;
+ return self;
+ };
+ this.zoomout = function(fn) {
+ this.onzoomout = fn;
+ return self;
+ };
+
+ this.isScrollable = function(e) {
+ var dom = (e.target) ? e.target : e;
+ if (dom.nodeName == 'OPTION') return true;
+ while (dom && (dom.nodeType == 1) && !(/^BODY|HTML/.test(dom.nodeName))) {
+ var dd = $(dom);
+ var ov = dd.css('overflowY') || dd.css('overflowX') || dd.css('overflow') || '';
+ if (/scroll|auto/.test(ov)) return (dom.clientHeight != dom.scrollHeight);
+ dom = (dom.parentNode) ? dom.parentNode : false;
+ }
+ return false;
+ };
+
+ this.getViewport = function(me) {
+ var dom = (me && me.parentNode) ? me.parentNode : false;
+ while (dom && (dom.nodeType == 1) && !(/^BODY|HTML/.test(dom.nodeName))) {
+ var dd = $(dom);
+ if (/fixed|absolute/.test(dd.css("position"))) return dd;
+ var ov = dd.css('overflowY') || dd.css('overflowX') || dd.css('overflow') || '';
+ if ((/scroll|auto/.test(ov)) && (dom.clientHeight != dom.scrollHeight)) return dd;
+ if (dd.getNiceScroll().length > 0) return dd;
+ dom = (dom.parentNode) ? dom.parentNode : false;
+ }
+ return false; //(dom) ? $(dom) : false;
+ };
+
+ this.triggerScrollEnd = function() {
+ if (!self.onscrollend) return;
+
+ var px = self.getScrollLeft();
+ var py = self.getScrollTop();
+
+ var info = {
+ "type": "scrollend",
+ "current": {
+ "x": px,
+ "y": py
+ },
+ "end": {
+ "x": px,
+ "y": py
+ }
+ };
+ self.onscrollend.call(self, info);
+ }
+
+ function execScrollWheel(e, hr, chkscroll) {
+ var px, py;
+
+ if (e.deltaMode == 0) { // PIXEL
+ px = -Math.floor(e.deltaX * (self.opt.mousescrollstep / (18 * 3)));
+ py = -Math.floor(e.deltaY * (self.opt.mousescrollstep / (18 * 3)));
+ } else if (e.deltaMode == 1) { // LINE
+ px = -Math.floor(e.deltaX * self.opt.mousescrollstep);
+ py = -Math.floor(e.deltaY * self.opt.mousescrollstep);
+ }
+
+ if (hr && self.opt.oneaxismousemode && (px == 0) && py) { // classic vertical-only mousewheel + browser with x/y support
+ px = py;
+ py = 0;
+
+ if (chkscroll) {
+ var hrend = (px < 0) ? (self.getScrollLeft() >= self.page.maxw) : (self.getScrollLeft() <= 0);
+ if (hrend) { // preserve vertical scrolling
+ py = px;
+ px = 0;
+ }
+ }
+
+ }
+
+ if (px) {
+ if (self.scrollmom) {
+ self.scrollmom.stop()
+ }
+ self.lastdeltax += px;
+ self.debounced("mousewheelx", function() {
+ var dt = self.lastdeltax;
+ self.lastdeltax = 0;
+ if (!self.rail.drag) {
+ self.doScrollLeftBy(dt)
+ }
+ }, 15);
+ }
+ if (py) {
+ if (self.opt.nativeparentscrolling && chkscroll && !self.ispage && !self.zoomactive) {
+ if (py < 0) {
+ if (self.getScrollTop() >= self.page.maxh) return true;
+ } else {
+ if (self.getScrollTop() <= 0) return true;
+ }
+ }
+ if (self.scrollmom) {
+ self.scrollmom.stop()
+ }
+ self.lastdeltay += py;
+ self.debounced("mousewheely", function() {
+ var dt = self.lastdeltay;
+ self.lastdeltay = 0;
+ if (!self.rail.drag) {
+ self.doScrollBy(dt)
+ }
+ }, 15);
+ }
+
+ e.stopImmediatePropagation();
+ return e.preventDefault();
+ };
+
+ this.onmousewheel = function(e) {
+ if (self.wheelprevented) return;
+ if (self.railslocked) {
+ self.debounced("checkunlock", self.resize, 250);
+ return true;
+ }
+ if (self.rail.drag) return self.cancelEvent(e);
+
+ if (self.opt.oneaxismousemode == "auto" && e.deltaX != 0) self.opt.oneaxismousemode = false; // check two-axis mouse support (not very elegant)
+
+ if (self.opt.oneaxismousemode && e.deltaX == 0) {
+ if (!self.rail.scrollable) {
+ if (self.railh && self.railh.scrollable) {
+ return self.onmousewheelhr(e);
+ } else {
+ return true;
+ }
+ }
+ }
+
+ var nw = +(new Date());
+ var chk = false;
+ if (self.opt.preservenativescrolling && ((self.checkarea + 600) < nw)) {
+ self.nativescrollingarea = self.isScrollable(e);
+ chk = true;
+ }
+ self.checkarea = nw;
+ if (self.nativescrollingarea) return true; // this isn't my business
+ var ret = execScrollWheel(e, false, chk);
+ if (ret) self.checkarea = 0;
+ return ret;
+ };
+
+ this.onmousewheelhr = function(e) {
+ if (self.wheelprevented) return;
+ if (self.railslocked || !self.railh.scrollable) return true;
+ if (self.rail.drag) return self.cancelEvent(e);
+
+ var nw = +(new Date());
+ var chk = false;
+ if (self.opt.preservenativescrolling && ((self.checkarea + 600) < nw)) {
+ self.nativescrollingarea = self.isScrollable(e);
+ chk = true;
+ }
+ self.checkarea = nw;
+ if (self.nativescrollingarea) return true; // this isn't my business
+ if (self.railslocked) return self.cancelEvent(e);
+
+ return execScrollWheel(e, true, chk);
+ };
+
+ this.stop = function() {
+ self.cancelScroll();
+ if (self.scrollmon) self.scrollmon.stop();
+ self.cursorfreezed = false;
+ self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y));
+ self.noticeCursor();
+ return self;
+ };
+
+ this.getTransitionSpeed = function(dif) {
+ var sp = Math.round(self.opt.scrollspeed * 10);
+ var ex = Math.min(sp, Math.round((dif / 20) * self.opt.scrollspeed));
+ return (ex > 20) ? ex : 0;
+ };
+
+ if (!self.opt.smoothscroll) {
+ this.doScrollLeft = function(x, spd) { //direct
+ var y = self.getScrollTop();
+ self.doScrollPos(x, y, spd);
+ };
+ this.doScrollTop = function(y, spd) { //direct
+ var x = self.getScrollLeft();
+ self.doScrollPos(x, y, spd);
+ };
+ this.doScrollPos = function(x, y, spd) { //direct
+ var nx = (x > self.page.maxw) ? self.page.maxw : x;
+ if (nx < 0) nx = 0;
+ var ny = (y > self.page.maxh) ? self.page.maxh : y;
+ if (ny < 0) ny = 0;
+ self.synched('scroll', function() {
+ self.setScrollTop(ny);
+ self.setScrollLeft(nx);
+ });
+ };
+ this.cancelScroll = function() {}; // direct
+ } else if (self.ishwscroll && cap.hastransition && self.opt.usetransition && !!self.opt.smoothscroll) {
+ this.prepareTransition = function(dif, istime) {
+ var ex = (istime) ? ((dif > 20) ? dif : 0) : self.getTransitionSpeed(dif);
+ var trans = (ex) ? cap.prefixstyle + 'transform ' + ex + 'ms ease-out' : '';
+ if (!self.lasttransitionstyle || self.lasttransitionstyle != trans) {
+ self.lasttransitionstyle = trans;
+ self.doc.css(cap.transitionstyle, trans);
+ }
+ return ex;
+ };
+
+ this.doScrollLeft = function(x, spd) { //trans
+ var y = (self.scrollrunning) ? self.newscrolly : self.getScrollTop();
+ self.doScrollPos(x, y, spd);
+ };
+
+ this.doScrollTop = function(y, spd) { //trans
+ var x = (self.scrollrunning) ? self.newscrollx : self.getScrollLeft();
+ self.doScrollPos(x, y, spd);
+ };
+
+ this.doScrollPos = function(x, y, spd) { //trans
+
+ var py = self.getScrollTop();
+ var px = self.getScrollLeft();
+
+ if (((self.newscrolly - py) * (y - py) < 0) || ((self.newscrollx - px) * (x - px) < 0)) self.cancelScroll(); //inverted movement detection
+
+ if (self.opt.bouncescroll == false) {
+ if (y < 0) y = 0;
+ else if (y > self.page.maxh) y = self.page.maxh;
+ if (x < 0) x = 0;
+ else if (x > self.page.maxw) x = self.page.maxw;
+ }
+
+ if (self.scrollrunning && x == self.newscrollx && y == self.newscrolly) return false;
+
+ self.newscrolly = y;
+ self.newscrollx = x;
+
+ self.newscrollspeed = spd || false;
+
+ if (self.timer) return false;
+
+ self.timer = setTimeout(function() {
+
+ var top = self.getScrollTop();
+ var lft = self.getScrollLeft();
+
+ var dst = {};
+ dst.x = x - lft;
+ dst.y = y - top;
+ dst.px = lft;
+ dst.py = top;
+
+ var dd = Math.round(Math.sqrt(Math.pow(dst.x, 2) + Math.pow(dst.y, 2)));
+ var ms = (self.newscrollspeed && self.newscrollspeed > 1) ? self.newscrollspeed : self.getTransitionSpeed(dd);
+ if (self.newscrollspeed && self.newscrollspeed <= 1) ms *= self.newscrollspeed;
+
+ self.prepareTransition(ms, true);
+
+ if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm);
+
+ if (ms > 0) {
+
+ if (!self.scrollrunning && self.onscrollstart) {
+ var info = {
+ "type": "scrollstart",
+ "current": {
+ "x": lft,
+ "y": top
+ },
+ "request": {
+ "x": x,
+ "y": y
+ },
+ "end": {
+ "x": self.newscrollx,
+ "y": self.newscrolly
+ },
+ "speed": ms
+ };
+ self.onscrollstart.call(self, info);
+ }
+
+ if (cap.transitionend) {
+ if (!self.scrollendtrapped) {
+ self.scrollendtrapped = true;
+ self.bind(self.doc, cap.transitionend, self.onScrollTransitionEnd, false); //I have got to do something usefull!!
+ }
+ } else {
+ if (self.scrollendtrapped) clearTimeout(self.scrollendtrapped);
+ self.scrollendtrapped = setTimeout(self.onScrollTransitionEnd, ms); // simulate transitionend event
+ }
+
+ var py = top;
+ var px = lft;
+ self.timerscroll = {
+ bz: new BezierClass(py, self.newscrolly, ms, 0, 0, 0.58, 1),
+ bh: new BezierClass(px, self.newscrollx, ms, 0, 0, 0.58, 1)
+ };
+ if (!self.cursorfreezed) self.timerscroll.tm = setInterval(function() {
+ self.showCursor(self.getScrollTop(), self.getScrollLeft())
+ }, 60);
+
+ }
+
+ self.synched("doScroll-set", function() {
+ self.timer = 0;
+ if (self.scrollendtrapped) self.scrollrunning = true;
+ self.setScrollTop(self.newscrolly);
+ self.setScrollLeft(self.newscrollx);
+ if (!self.scrollendtrapped) self.onScrollTransitionEnd();
+ });
+
+
+ }, 50);
+
+ };
+
+ this.cancelScroll = function() {
+ if (!self.scrollendtrapped) return true;
+ var py = self.getScrollTop();
+ var px = self.getScrollLeft();
+ self.scrollrunning = false;
+ if (!cap.transitionend) clearTimeout(cap.transitionend);
+ self.scrollendtrapped = false;
+ self._unbind(self.doc[0], cap.transitionend, self.onScrollTransitionEnd);
+ self.prepareTransition(0);
+ self.setScrollTop(py); // fire event onscroll
+ if (self.railh) self.setScrollLeft(px);
+ if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm);
+ self.timerscroll = false;
+
+ self.cursorfreezed = false;
+
+ self.showCursor(py, px);
+ return self;
+ };
+ this.onScrollTransitionEnd = function() {
+ if (self.scrollendtrapped) self._unbind(self.doc[0], cap.transitionend, self.onScrollTransitionEnd);
+ self.scrollendtrapped = false;
+ self.prepareTransition(0);
+ if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm);
+ self.timerscroll = false;
+ var py = self.getScrollTop();
+ var px = self.getScrollLeft();
+ self.setScrollTop(py); // fire event onscroll
+ if (self.railh) self.setScrollLeft(px); // fire event onscroll left
+
+ self.noticeCursor(false, py, px);
+
+ self.cursorfreezed = false;
+
+ if (py < 0) py = 0
+ else if (py > self.page.maxh) py = self.page.maxh;
+ if (px < 0) px = 0
+ else if (px > self.page.maxw) px = self.page.maxw;
+ if ((py != self.newscrolly) || (px != self.newscrollx)) return self.doScrollPos(px, py, self.opt.snapbackspeed);
+
+ if (self.onscrollend && self.scrollrunning) {
+ self.triggerScrollEnd();
+ }
+ self.scrollrunning = false;
+
+ };
+
+ } else {
+
+ this.doScrollLeft = function(x, spd) { //no-trans
+ var y = (self.scrollrunning) ? self.newscrolly : self.getScrollTop();
+ self.doScrollPos(x, y, spd);
+ };
+
+ this.doScrollTop = function(y, spd) { //no-trans
+ var x = (self.scrollrunning) ? self.newscrollx : self.getScrollLeft();
+ self.doScrollPos(x, y, spd);
+ };
+
+ this.doScrollPos = function(x, y, spd) { //no-trans
+ var y = ((typeof y == "undefined") || (y === false)) ? self.getScrollTop(true) : y;
+
+ if ((self.timer) && (self.newscrolly == y) && (self.newscrollx == x)) return true;
+
+ if (self.timer) clearAnimationFrame(self.timer);
+ self.timer = 0;
+
+ var py = self.getScrollTop();
+ var px = self.getScrollLeft();
+
+ if (((self.newscrolly - py) * (y - py) < 0) || ((self.newscrollx - px) * (x - px) < 0)) self.cancelScroll(); //inverted movement detection
+
+ self.newscrolly = y;
+ self.newscrollx = x;
+
+ if (!self.bouncescroll || !self.rail.visibility) {
+ if (self.newscrolly < 0) {
+ self.newscrolly = 0;
+ } else if (self.newscrolly > self.page.maxh) {
+ self.newscrolly = self.page.maxh;
+ }
+ }
+ if (!self.bouncescroll || !self.railh.visibility) {
+ if (self.newscrollx < 0) {
+ self.newscrollx = 0;
+ } else if (self.newscrollx > self.page.maxw) {
+ self.newscrollx = self.page.maxw;
+ }
+ }
+
+ self.dst = {};
+ self.dst.x = x - px;
+ self.dst.y = y - py;
+ self.dst.px = px;
+ self.dst.py = py;
+
+ var dst = Math.round(Math.sqrt(Math.pow(self.dst.x, 2) + Math.pow(self.dst.y, 2)));
+
+ self.dst.ax = self.dst.x / dst;
+ self.dst.ay = self.dst.y / dst;
+
+ var pa = 0;
+ var pe = dst;
+
+ if (self.dst.x == 0) {
+ pa = py;
+ pe = y;
+ self.dst.ay = 1;
+ self.dst.py = 0;
+ } else if (self.dst.y == 0) {
+ pa = px;
+ pe = x;
+ self.dst.ax = 1;
+ self.dst.px = 0;
+ }
+
+ var ms = self.getTransitionSpeed(dst);
+ if (spd && spd <= 1) ms *= spd;
+ if (ms > 0) {
+ self.bzscroll = (self.bzscroll) ? self.bzscroll.update(pe, ms) : new BezierClass(pa, pe, ms, 0, 1, 0, 1);
+ } else {
+ self.bzscroll = false;
+ }
+
+ if (self.timer) return;
+
+ if ((py == self.page.maxh && y >= self.page.maxh) || (px == self.page.maxw && x >= self.page.maxw)) self.checkContentSize();
+
+ var sync = 1;
+
+ function scrolling() {
+ if (self.cancelAnimationFrame) return true;
+
+ self.scrollrunning = true;
+
+ sync = 1 - sync;
+ if (sync) return (self.timer = setAnimationFrame(scrolling) || 1);
+
+ var done = 0;
+ var sx, sy;
+
+ var sc = sy = self.getScrollTop();
+ if (self.dst.ay) {
+ sc = (self.bzscroll) ? self.dst.py + (self.bzscroll.getNow() * self.dst.ay) : self.newscrolly;
+ var dr = sc - sy;
+ if ((dr < 0 && sc < self.newscrolly) || (dr > 0 && sc > self.newscrolly)) sc = self.newscrolly;
+ self.setScrollTop(sc);
+ if (sc == self.newscrolly) done = 1;
+ } else {
+ done = 1;
+ }
+
+ var scx = sx = self.getScrollLeft();
+ if (self.dst.ax) {
+ scx = (self.bzscroll) ? self.dst.px + (self.bzscroll.getNow() * self.dst.ax) : self.newscrollx;
+ var dr = scx - sx;
+ if ((dr < 0 && scx < self.newscrollx) || (dr > 0 && scx > self.newscrollx)) scx = self.newscrollx;
+ self.setScrollLeft(scx);
+ if (scx == self.newscrollx) done += 1;
+ } else {
+ done += 1;
+ }
+
+ if (done == 2) {
+ self.timer = 0;
+ self.cursorfreezed = false;
+ self.bzscroll = false;
+ self.scrollrunning = false;
+ if (sc < 0) sc = 0;
+ else if (sc > self.page.maxh) sc = self.page.maxh;
+ if (scx < 0) scx = 0;
+ else if (scx > self.page.maxw) scx = self.page.maxw;
+ if ((scx != self.newscrollx) || (sc != self.newscrolly)) self.doScrollPos(scx, sc);
+ else {
+ if (self.onscrollend) {
+ self.triggerScrollEnd();
+ }
+ }
+ } else {
+ self.timer = setAnimationFrame(scrolling) || 1;
+ }
+ };
+ self.cancelAnimationFrame = false;
+ self.timer = 1;
+
+ if (self.onscrollstart && !self.scrollrunning) {
+ var info = {
+ "type": "scrollstart",
+ "current": {
+ "x": px,
+ "y": py
+ },
+ "request": {
+ "x": x,
+ "y": y
+ },
+ "end": {
+ "x": self.newscrollx,
+ "y": self.newscrolly
+ },
+ "speed": ms
+ };
+ self.onscrollstart.call(self, info);
+ }
+
+ scrolling();
+
+ if ((py == self.page.maxh && y >= py) || (px == self.page.maxw && x >= px)) self.checkContentSize();
+
+ self.noticeCursor();
+ };
+
+ this.cancelScroll = function() {
+ if (self.timer) clearAnimationFrame(self.timer);
+ self.timer = 0;
+ self.bzscroll = false;
+ self.scrollrunning = false;
+ return self;
+ };
+
+ }
+
+ this.doScrollBy = function(stp, relative) {
+ var ny = 0;
+ if (relative) {
+ ny = Math.floor((self.scroll.y - stp) * self.scrollratio.y)
+ } else {
+ var sy = (self.timer) ? self.newscrolly : self.getScrollTop(true);
+ ny = sy - stp;
+ }
+ if (self.bouncescroll) {
+ var haf = Math.round(self.view.h / 2);
+ if (ny < -haf) ny = -haf
+ else if (ny > (self.page.maxh + haf)) ny = (self.page.maxh + haf);
+ }
+ self.cursorfreezed = false;
+
+ var py = self.getScrollTop(true);
+ if (ny < 0 && py <= 0) return self.noticeCursor();
+ else if (ny > self.page.maxh && py >= self.page.maxh) {
+ self.checkContentSize();
+ return self.noticeCursor();
+ }
+
+ self.doScrollTop(ny);
+ };
+
+ this.doScrollLeftBy = function(stp, relative) {
+ var nx = 0;
+ if (relative) {
+ nx = Math.floor((self.scroll.x - stp) * self.scrollratio.x)
+ } else {
+ var sx = (self.timer) ? self.newscrollx : self.getScrollLeft(true);
+ nx = sx - stp;
+ }
+ if (self.bouncescroll) {
+ var haf = Math.round(self.view.w / 2);
+ if (nx < -haf) nx = -haf;
+ else if (nx > (self.page.maxw + haf)) nx = (self.page.maxw + haf);
+ }
+ self.cursorfreezed = false;
+
+ var px = self.getScrollLeft(true);
+ if (nx < 0 && px <= 0) return self.noticeCursor();
+ else if (nx > self.page.maxw && px >= self.page.maxw) return self.noticeCursor();
+
+ self.doScrollLeft(nx);
+ };
+
+ this.doScrollTo = function(pos, relative) {
+ var ny = (relative) ? Math.round(pos * self.scrollratio.y) : pos;
+ if (ny < 0) ny = 0;
+ else if (ny > self.page.maxh) ny = self.page.maxh;
+ self.cursorfreezed = false;
+ self.doScrollTop(pos);
+ };
+
+ this.checkContentSize = function() {
+ var pg = self.getContentSize();
+ if ((pg.h != self.page.h) || (pg.w != self.page.w)) self.resize(false, pg);
+ };
+
+ self.onscroll = function(e) {
+ if (self.rail.drag) return;
+ if (!self.cursorfreezed) {
+ self.synched('scroll', function() {
+ self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y));
+ if (self.railh) self.scroll.x = Math.round(self.getScrollLeft() * (1 / self.scrollratio.x));
+ self.noticeCursor();
+ });
+ }
+ };
+ self.bind(self.docscroll, "scroll", self.onscroll);
+
+ this.doZoomIn = function(e) {
+ if (self.zoomactive) return;
+ self.zoomactive = true;
+
+ self.zoomrestore = {
+ style: {}
+ };
+ var lst = ['position', 'top', 'left', 'zIndex', 'backgroundColor', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight'];
+ var win = self.win[0].style;
+ for (var a in lst) {
+ var pp = lst[a];
+ self.zoomrestore.style[pp] = (typeof win[pp] != "undefined") ? win[pp] : '';
+ }
+
+ self.zoomrestore.style.width = self.win.css('width');
+ self.zoomrestore.style.height = self.win.css('height');
+
+ self.zoomrestore.padding = {
+ w: self.win.outerWidth() - self.win.width(),
+ h: self.win.outerHeight() - self.win.height()
+ };
+
+ if (cap.isios4) {
+ self.zoomrestore.scrollTop = $(window).scrollTop();
+ $(window).scrollTop(0);
+ }
+
+ self.win.css({
+ "position": (cap.isios4) ? "absolute" : "fixed",
+ "top": 0,
+ "left": 0,
+ "z-index": globalmaxzindex + 100,
+ "margin": "0px"
+ });
+ var bkg = self.win.css("backgroundColor");
+ if (bkg == "" || /transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(bkg)) self.win.css("backgroundColor", "#fff");
+ self.rail.css({
+ "z-index": globalmaxzindex + 101
+ });
+ self.zoom.css({
+ "z-index": globalmaxzindex + 102
+ });
+ self.zoom.css('backgroundPosition', '0px -18px');
+ self.resizeZoom();
+
+ if (self.onzoomin) self.onzoomin.call(self);
+
+ return self.cancelEvent(e);
+ };
+
+ this.doZoomOut = function(e) {
+ if (!self.zoomactive) return;
+ self.zoomactive = false;
+
+ self.win.css("margin", "");
+ self.win.css(self.zoomrestore.style);
+
+ if (cap.isios4) {
+ $(window).scrollTop(self.zoomrestore.scrollTop);
+ }
+
+ self.rail.css({
+ "z-index": self.zindex
+ });
+ self.zoom.css({
+ "z-index": self.zindex
+ });
+ self.zoomrestore = false;
+ self.zoom.css('backgroundPosition', '0px 0px');
+ self.onResize();
+
+ if (self.onzoomout) self.onzoomout.call(self);
+
+ return self.cancelEvent(e);
+ };
+
+ this.doZoom = function(e) {
+ return (self.zoomactive) ? self.doZoomOut(e) : self.doZoomIn(e);
+ };
+
+ this.resizeZoom = function() {
+ if (!self.zoomactive) return;
+
+ var py = self.getScrollTop(); //preserve scrolling position
+ self.win.css({
+ width: $(window).width() - self.zoomrestore.padding.w + "px",
+ height: $(window).height() - self.zoomrestore.padding.h + "px"
+ });
+ self.onResize();
+
+ self.setScrollTop(Math.min(self.page.maxh, py));
+ };
+
+ this.init();
+
+ $.nicescroll.push(this);
+
+ };
+
+ // Inspired by the work of Kin Blas
+ // http://webpro.host.adobe.com/people/jblas/momentum/includes/jquery.momentum.0.7.js
+
+
+ var ScrollMomentumClass2D = function(nc) {
+ var self = this;
+ this.nc = nc;
+
+ this.lastx = 0;
+ this.lasty = 0;
+ this.speedx = 0;
+ this.speedy = 0;
+ this.lasttime = 0;
+ this.steptime = 0;
+ this.snapx = false;
+ this.snapy = false;
+ this.demulx = 0;
+ this.demuly = 0;
+
+ this.lastscrollx = -1;
+ this.lastscrolly = -1;
+
+ this.chkx = 0;
+ this.chky = 0;
+
+ this.timer = 0;
+
+ this.time = function() {
+ return +new Date(); //beautifull hack
+ };
+
+ this.reset = function(px, py) {
+ self.stop();
+ var now = self.time();
+ self.steptime = 0;
+ self.lasttime = now;
+ self.speedx = 0;
+ self.speedy = 0;
+ self.lastx = px;
+ self.lasty = py;
+ self.lastscrollx = -1;
+ self.lastscrolly = -1;
+ };
+
+ this.update = function(px, py) {
+ var now = self.time();
+ self.steptime = now - self.lasttime;
+ self.lasttime = now;
+ var dy = py - self.lasty;
+ var dx = px - self.lastx;
+ var sy = self.nc.getScrollTop();
+ var sx = self.nc.getScrollLeft();
+ var newy = sy + dy;
+ var newx = sx + dx;
+ self.snapx = (newx < 0) || (newx > self.nc.page.maxw);
+ self.snapy = (newy < 0) || (newy > self.nc.page.maxh);
+ self.speedx = dx;
+ self.speedy = dy;
+ self.lastx = px;
+ self.lasty = py;
+ };
+
+ this.stop = function() {
+ self.nc.unsynched("domomentum2d");
+ if (self.timer) clearTimeout(self.timer);
+ self.timer = 0;
+ self.lastscrollx = -1;
+ self.lastscrolly = -1;
+ };
+
+ this.doSnapy = function(nx, ny) {
+ var snap = false;
+
+ if (ny < 0) {
+ ny = 0;
+ snap = true;
+ } else if (ny > self.nc.page.maxh) {
+ ny = self.nc.page.maxh;
+ snap = true;
+ }
+
+ if (nx < 0) {
+ nx = 0;
+ snap = true;
+ } else if (nx > self.nc.page.maxw) {
+ nx = self.nc.page.maxw;
+ snap = true;
+ }
+
+ (snap) ? self.nc.doScrollPos(nx, ny, self.nc.opt.snapbackspeed): self.nc.triggerScrollEnd();
+ };
+
+ this.doMomentum = function(gp) {
+ var t = self.time();
+ var l = (gp) ? t + gp : self.lasttime;
+
+ var sl = self.nc.getScrollLeft();
+ var st = self.nc.getScrollTop();
+
+ var pageh = self.nc.page.maxh;
+ var pagew = self.nc.page.maxw;
+
+ self.speedx = (pagew > 0) ? Math.min(60, self.speedx) : 0;
+ self.speedy = (pageh > 0) ? Math.min(60, self.speedy) : 0;
+
+ var chk = l && (t - l) <= 60;
+
+ if ((st < 0) || (st > pageh) || (sl < 0) || (sl > pagew)) chk = false;
+
+ var sy = (self.speedy && chk) ? self.speedy : false;
+ var sx = (self.speedx && chk) ? self.speedx : false;
+
+ if (sy || sx) {
+ var tm = Math.max(16, self.steptime); //timeout granularity
+
+ if (tm > 50) { // do smooth
+ var xm = tm / 50;
+ self.speedx *= xm;
+ self.speedy *= xm;
+ tm = 50;
+ }
+
+ self.demulxy = 0;
+
+ self.lastscrollx = self.nc.getScrollLeft();
+ self.chkx = self.lastscrollx;
+ self.lastscrolly = self.nc.getScrollTop();
+ self.chky = self.lastscrolly;
+
+ var nx = self.lastscrollx;
+ var ny = self.lastscrolly;
+
+ var onscroll = function() {
+ var df = ((self.time() - t) > 600) ? 0.04 : 0.02;
+
+ if (self.speedx) {
+ nx = Math.floor(self.lastscrollx - (self.speedx * (1 - self.demulxy)));
+ self.lastscrollx = nx;
+ if ((nx < 0) || (nx > pagew)) df = 0.10;
+ }
+
+ if (self.speedy) {
+ ny = Math.floor(self.lastscrolly - (self.speedy * (1 - self.demulxy)));
+ self.lastscrolly = ny;
+ if ((ny < 0) || (ny > pageh)) df = 0.10;
+ }
+
+ self.demulxy = Math.min(1, self.demulxy + df);
+
+ self.nc.synched("domomentum2d", function() {
+
+ if (self.speedx) {
+ var scx = self.nc.getScrollLeft();
+ if (scx != self.chkx) self.stop();
+ self.chkx = nx;
+ self.nc.setScrollLeft(nx);
+ }
+
+ if (self.speedy) {
+ var scy = self.nc.getScrollTop();
+ if (scy != self.chky) self.stop();
+ self.chky = ny;
+ self.nc.setScrollTop(ny);
+ }
+
+ if (!self.timer) {
+ self.nc.hideCursor();
+ self.doSnapy(nx, ny);
+ }
+
+ });
+
+ if (self.demulxy < 1) {
+ self.timer = setTimeout(onscroll, tm);
+ } else {
+ self.stop();
+ self.nc.hideCursor();
+ self.doSnapy(nx, ny);
+ }
+ };
+
+ onscroll();
+
+ } else {
+ self.doSnapy(self.nc.getScrollLeft(), self.nc.getScrollTop());
+ }
+
+ }
+
+ };
+
+
+ // override jQuery scrollTop
+
+ var _scrollTop = jQuery.fn.scrollTop; // preserve original function
+
+ jQuery.cssHooks["pageYOffset"] = {
+ get: function(elem, computed, extra) {
+ var nice = $.data(elem, '__nicescroll') || false;
+ return (nice && nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(elem);
+ },
+ set: function(elem, value) {
+ var nice = $.data(elem, '__nicescroll') || false;
+ (nice && nice.ishwscroll) ? nice.setScrollTop(parseInt(value)): _scrollTop.call(elem, value);
+ return this;
+ }
+ };
+
+ /*
+ $.fx.step["scrollTop"] = function(fx){
+ $.cssHooks["scrollTop"].set( fx.elem, fx.now + fx.unit );
+ };
+*/
+
+ jQuery.fn.scrollTop = function(value) {
+ if (typeof value == "undefined") {
+ var nice = (this[0]) ? $.data(this[0], '__nicescroll') || false : false;
+ return (nice && nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(this);
+ } else {
+ return this.each(function() {
+ var nice = $.data(this, '__nicescroll') || false;
+ (nice && nice.ishwscroll) ? nice.setScrollTop(parseInt(value)): _scrollTop.call($(this), value);
+ });
+ }
+ };
+
+ // override jQuery scrollLeft
+
+ var _scrollLeft = jQuery.fn.scrollLeft; // preserve original function
+
+ $.cssHooks.pageXOffset = {
+ get: function(elem, computed, extra) {
+ var nice = $.data(elem, '__nicescroll') || false;
+ return (nice && nice.ishwscroll) ? nice.getScrollLeft() : _scrollLeft.call(elem);
+ },
+ set: function(elem, value) {
+ var nice = $.data(elem, '__nicescroll') || false;
+ (nice && nice.ishwscroll) ? nice.setScrollLeft(parseInt(value)): _scrollLeft.call(elem, value);
+ return this;
+ }
+ };
+
+ /*
+ $.fx.step["scrollLeft"] = function(fx){
+ $.cssHooks["scrollLeft"].set( fx.elem, fx.now + fx.unit );
+ };
+*/
+
+ jQuery.fn.scrollLeft = function(value) {
+ if (typeof value == "undefined") {
+ var nice = (this[0]) ? $.data(this[0], '__nicescroll') || false : false;
+ return (nice && nice.ishwscroll) ? nice.getScrollLeft() : _scrollLeft.call(this);
+ } else {
+ return this.each(function() {
+ var nice = $.data(this, '__nicescroll') || false;
+ (nice && nice.ishwscroll) ? nice.setScrollLeft(parseInt(value)): _scrollLeft.call($(this), value);
+ });
+ }
+ };
+
+ var NiceScrollArray = function(doms) {
+ var self = this;
+ this.length = 0;
+ this.name = "nicescrollarray";
+
+ this.each = function(fn) {
+ for (var a = 0, i = 0; a < self.length; a++) fn.call(self[a], i++);
+ return self;
+ };
+
+ this.push = function(nice) {
+ self[self.length] = nice;
+ self.length++;
+ };
+
+ this.eq = function(idx) {
+ return self[idx];
+ };
+
+ if (doms) {
+ for (var a = 0; a < doms.length; a++) {
+ var nice = $.data(doms[a], '__nicescroll') || false;
+ if (nice) {
+ this[this.length] = nice;
+ this.length++;
+ }
+ };
+ }
+
+ return this;
+ };
+
+ function mplex(el, lst, fn) {
+ for (var a = 0; a < lst.length; a++) fn(el, lst[a]);
+ };
+ mplex(
+ NiceScrollArray.prototype, ['show', 'hide', 'toggle', 'onResize', 'resize', 'remove', 'stop', 'doScrollPos'],
+ function(e, n) {
+ e[n] = function() {
+ var args = arguments;
+ return this.each(function() {
+ this[n].apply(this, args);
+ });
+ };
+ }
+ );
+
+ jQuery.fn.getNiceScroll = function(index) {
+ if (typeof index == "undefined") {
+ return new NiceScrollArray(this);
+ } else {
+ var nice = this[index] && $.data(this[index], '__nicescroll') || false;
+ return nice;
+ }
+ };
+
+ jQuery.extend(jQuery.expr[':'], {
+ nicescroll: function(a) {
+ return ($.data(a, '__nicescroll')) ? true : false;
+ }
+ });
+
+ $.fn.niceScroll = function(wrapper, opt) {
+ if (typeof opt == "undefined") {
+ if ((typeof wrapper == "object") && !("jquery" in wrapper)) {
+ opt = wrapper;
+ wrapper = false;
+ }
+ }
+ opt = $.extend({},opt); // cloning
+ var ret = new NiceScrollArray();
+ if (typeof opt == "undefined") opt = {};
+
+ if (wrapper || false) {
+ opt.doc = $(wrapper);
+ opt.win = $(this);
+ }
+ var docundef = !("doc" in opt);
+ if (!docundef && !("win" in opt)) opt.win = $(this);
+
+ this.each(function() {
+ var nice = $(this).data('__nicescroll') || false;
+ if (!nice) {
+ opt.doc = (docundef) ? $(this) : opt.doc;
+ nice = new NiceScrollClass(opt, $(this));
+ $(this).data('__nicescroll', nice);
+ }
+ ret.push(nice);
+ });
+ return (ret.length == 1) ? ret[0] : ret;
+ };
+
+ window.NiceScroll = {
+ getjQuery: function() {
+ return jQuery
+ }
+ };
+
+ if (!$.nicescroll) {
+ $.nicescroll = new NiceScrollArray();
+ $.nicescroll.options = _globaloptions;
+ }
+
+})); \ No newline at end of file
diff --git a/vendor/assets/javascripts/jquery.nicescroll.min.js b/vendor/assets/javascripts/jquery.nicescroll.min.js
deleted file mode 100644
index 5440b6a0da0..00000000000
--- a/vendor/assets/javascripts/jquery.nicescroll.min.js
+++ /dev/null
@@ -1,118 +0,0 @@
-/* jquery.nicescroll 3.6.0 InuYaksa*2014 MIT http://nicescroll.areaaperta.com */(function(f){"function"===typeof define&&define.amd?define(["jquery"],f):f(jQuery)})(function(f){var y=!1,D=!1,N=0,O=2E3,x=0,H=["webkit","ms","moz","o"],s=window.requestAnimationFrame||!1,t=window.cancelAnimationFrame||!1;if(!s)for(var P in H){var E=H[P];s||(s=window[E+"RequestAnimationFrame"]);t||(t=window[E+"CancelAnimationFrame"]||window[E+"CancelRequestAnimationFrame"])}var v=window.MutationObserver||window.WebKitMutationObserver||!1,I={zindex:"auto",cursoropacitymin:0,cursoropacitymax:1,cursorcolor:"#424242",
-cursorwidth:"5px",cursorborder:"1px solid #fff",cursorborderradius:"5px",scrollspeed:60,mousescrollstep:24,touchbehavior:!1,hwacceleration:!0,usetransition:!0,boxzoom:!1,dblclickzoom:!0,gesturezoom:!0,grabcursorenabled:!0,autohidemode:!0,background:"",iframeautoresize:!0,cursorminheight:32,preservenativescrolling:!0,railoffset:!1,railhoffset:!1,bouncescroll:!0,spacebarenabled:!0,railpadding:{top:0,right:0,left:0,bottom:0},disableoutline:!0,horizrailenabled:!0,railalign:"right",railvalign:"bottom",
-enabletranslate3d:!0,enablemousewheel:!0,enablekeyboard:!0,smoothscroll:!0,sensitiverail:!0,enablemouselockapi:!0,cursorfixedheight:!1,directionlockdeadzone:6,hidecursordelay:400,nativeparentscrolling:!0,enablescrollonselection:!0,overflowx:!0,overflowy:!0,cursordragspeed:.3,rtlmode:"auto",cursordragontouch:!1,oneaxismousemode:"auto",scriptpath:function(){var f=document.getElementsByTagName("script"),f=f[f.length-1].src.split("?")[0];return 0<f.split("/").length?f.split("/").slice(0,-1).join("/")+
-"/":""}(),preventmultitouchscrolling:!0},F=!1,Q=function(){if(F)return F;var f=document.createElement("DIV"),c=f.style,h=navigator.userAgent,m=navigator.platform,d={haspointerlock:"pointerLockElement"in document||"webkitPointerLockElement"in document||"mozPointerLockElement"in document};d.isopera="opera"in window;d.isopera12=d.isopera&&"getUserMedia"in navigator;d.isoperamini="[object OperaMini]"===Object.prototype.toString.call(window.operamini);d.isie="all"in document&&"attachEvent"in f&&!d.isopera;
-d.isieold=d.isie&&!("msInterpolationMode"in c);d.isie7=d.isie&&!d.isieold&&(!("documentMode"in document)||7==document.documentMode);d.isie8=d.isie&&"documentMode"in document&&8==document.documentMode;d.isie9=d.isie&&"performance"in window&&9<=document.documentMode;d.isie10=d.isie&&"performance"in window&&10==document.documentMode;d.isie11="msRequestFullscreen"in f&&11<=document.documentMode;d.isie9mobile=/iemobile.9/i.test(h);d.isie9mobile&&(d.isie9=!1);d.isie7mobile=!d.isie9mobile&&d.isie7&&/iemobile/i.test(h);
-d.ismozilla="MozAppearance"in c;d.iswebkit="WebkitAppearance"in c;d.ischrome="chrome"in window;d.ischrome22=d.ischrome&&d.haspointerlock;d.ischrome26=d.ischrome&&"transition"in c;d.cantouch="ontouchstart"in document.documentElement||"ontouchstart"in window;d.hasmstouch=window.MSPointerEvent||!1;d.hasw3ctouch=window.PointerEvent||!1;d.ismac=/^mac$/i.test(m);d.isios=d.cantouch&&/iphone|ipad|ipod/i.test(m);d.isios4=d.isios&&!("seal"in Object);d.isios7=d.isios&&"webkitHidden"in document;d.isandroid=/android/i.test(h);
-d.haseventlistener="addEventListener"in f;d.trstyle=!1;d.hastransform=!1;d.hastranslate3d=!1;d.transitionstyle=!1;d.hastransition=!1;d.transitionend=!1;m=["transform","msTransform","webkitTransform","MozTransform","OTransform"];for(h=0;h<m.length;h++)if("undefined"!=typeof c[m[h]]){d.trstyle=m[h];break}d.hastransform=!!d.trstyle;d.hastransform&&(c[d.trstyle]="translate3d(1px,2px,3px)",d.hastranslate3d=/translate3d/.test(c[d.trstyle]));d.transitionstyle=!1;d.prefixstyle="";d.transitionend=!1;for(var m=
-"transition webkitTransition msTransition MozTransition OTransition OTransition KhtmlTransition".split(" "),n=" -webkit- -ms- -moz- -o- -o -khtml-".split(" "),p="transitionend webkitTransitionEnd msTransitionEnd transitionend otransitionend oTransitionEnd KhtmlTransitionEnd".split(" "),h=0;h<m.length;h++)if(m[h]in c){d.transitionstyle=m[h];d.prefixstyle=n[h];d.transitionend=p[h];break}d.ischrome26&&(d.prefixstyle=n[1]);d.hastransition=d.transitionstyle;a:{h=["-webkit-grab","-moz-grab","grab"];if(d.ischrome&&
-!d.ischrome22||d.isie)h=[];for(m=0;m<h.length;m++)if(n=h[m],c.cursor=n,c.cursor==n){c=n;break a}c="url(//mail.google.com/mail/images/2/openhand.cur),n-resize"}d.cursorgrabvalue=c;d.hasmousecapture="setCapture"in f;d.hasMutationObserver=!1!==v;return F=d},R=function(k,c){function h(){var b=a.doc.css(e.trstyle);return b&&"matrix"==b.substr(0,6)?b.replace(/^.*\((.*)\)$/g,"$1").replace(/px/g,"").split(/, +/):!1}function m(){var b=a.win;if("zIndex"in b)return b.zIndex();for(;0<b.length&&9!=b[0].nodeType;){var g=
-b.css("zIndex");if(!isNaN(g)&&0!=g)return parseInt(g);b=b.parent()}return!1}function d(b,g,q){g=b.css(g);b=parseFloat(g);return isNaN(b)?(b=w[g]||0,q=3==b?q?a.win.outerHeight()-a.win.innerHeight():a.win.outerWidth()-a.win.innerWidth():1,a.isie8&&b&&(b+=1),q?b:0):b}function n(b,g,q,c){a._bind(b,g,function(a){a=a?a:window.event;var c={original:a,target:a.target||a.srcElement,type:"wheel",deltaMode:"MozMousePixelScroll"==a.type?0:1,deltaX:0,deltaZ:0,preventDefault:function(){a.preventDefault?a.preventDefault():
-a.returnValue=!1;return!1},stopImmediatePropagation:function(){a.stopImmediatePropagation?a.stopImmediatePropagation():a.cancelBubble=!0}};"mousewheel"==g?(c.deltaY=-.025*a.wheelDelta,a.wheelDeltaX&&(c.deltaX=-.025*a.wheelDeltaX)):c.deltaY=a.detail;return q.call(b,c)},c)}function p(b,g,c){var d,e;0==b.deltaMode?(d=-Math.floor(a.opt.mousescrollstep/54*b.deltaX),e=-Math.floor(a.opt.mousescrollstep/54*b.deltaY)):1==b.deltaMode&&(d=-Math.floor(b.deltaX*a.opt.mousescrollstep),e=-Math.floor(b.deltaY*a.opt.mousescrollstep));
-g&&a.opt.oneaxismousemode&&0==d&&e&&(d=e,e=0,c&&(0>d?a.getScrollLeft()>=a.page.maxw:0>=a.getScrollLeft())&&(e=d,d=0));d&&(a.scrollmom&&a.scrollmom.stop(),a.lastdeltax+=d,a.debounced("mousewheelx",function(){var b=a.lastdeltax;a.lastdeltax=0;a.rail.drag||a.doScrollLeftBy(b)},15));if(e){if(a.opt.nativeparentscrolling&&c&&!a.ispage&&!a.zoomactive)if(0>e){if(a.getScrollTop()>=a.page.maxh)return!0}else if(0>=a.getScrollTop())return!0;a.scrollmom&&a.scrollmom.stop();a.lastdeltay+=e;a.debounced("mousewheely",
-function(){var b=a.lastdeltay;a.lastdeltay=0;a.rail.drag||a.doScrollBy(b)},15)}b.stopImmediatePropagation();return b.preventDefault()}var a=this;this.version="3.6.0";this.name="nicescroll";this.me=c;this.opt={doc:f("body"),win:!1};f.extend(this.opt,I);this.opt.snapbackspeed=80;if(k)for(var G in a.opt)"undefined"!=typeof k[G]&&(a.opt[G]=k[G]);this.iddoc=(this.doc=a.opt.doc)&&this.doc[0]?this.doc[0].id||"":"";this.ispage=/^BODY|HTML/.test(a.opt.win?a.opt.win[0].nodeName:this.doc[0].nodeName);this.haswrapper=
-!1!==a.opt.win;this.win=a.opt.win||(this.ispage?f(window):this.doc);this.docscroll=this.ispage&&!this.haswrapper?f(window):this.win;this.body=f("body");this.iframe=this.isfixed=this.viewport=!1;this.isiframe="IFRAME"==this.doc[0].nodeName&&"IFRAME"==this.win[0].nodeName;this.istextarea="TEXTAREA"==this.win[0].nodeName;this.forcescreen=!1;this.canshowonmouseevent="scroll"!=a.opt.autohidemode;this.page=this.view=this.onzoomout=this.onzoomin=this.onscrollcancel=this.onscrollend=this.onscrollstart=this.onclick=
-this.ongesturezoom=this.onkeypress=this.onmousewheel=this.onmousemove=this.onmouseup=this.onmousedown=!1;this.scroll={x:0,y:0};this.scrollratio={x:0,y:0};this.cursorheight=20;this.scrollvaluemax=0;this.isrtlmode="auto"==this.opt.rtlmode?"rtl"==(this.win[0]==window?this.body:this.win).css("direction"):!0===this.opt.rtlmode;this.observerbody=this.observerremover=this.observer=this.scrollmom=this.scrollrunning=!1;do this.id="ascrail"+O++;while(document.getElementById(this.id));this.hasmousefocus=this.hasfocus=
-this.zoomactive=this.zoom=this.selectiondrag=this.cursorfreezed=this.cursor=this.rail=!1;this.visibility=!0;this.hidden=this.locked=this.railslocked=!1;this.cursoractive=!0;this.wheelprevented=!1;this.overflowx=a.opt.overflowx;this.overflowy=a.opt.overflowy;this.nativescrollingarea=!1;this.checkarea=0;this.events=[];this.saved={};this.delaylist={};this.synclist={};this.lastdeltay=this.lastdeltax=0;this.detected=Q();var e=f.extend({},this.detected);this.ishwscroll=(this.canhwscroll=e.hastransform&&
-a.opt.hwacceleration)&&a.haswrapper;this.hasreversehr=this.isrtlmode&&!e.iswebkit;this.istouchcapable=!1;!e.cantouch||e.isios||e.isandroid||!e.iswebkit&&!e.ismozilla||(this.istouchcapable=!0,e.cantouch=!1);a.opt.enablemouselockapi||(e.hasmousecapture=!1,e.haspointerlock=!1);this.debounced=function(b,g,c){var d=a.delaylist[b];a.delaylist[b]=g;d||setTimeout(function(){var g=a.delaylist[b];a.delaylist[b]=!1;g.call(a)},c)};var r=!1;this.synched=function(b,g){a.synclist[b]=g;(function(){r||(s(function(){r=
-!1;for(var b in a.synclist){var g=a.synclist[b];g&&g.call(a);a.synclist[b]=!1}}),r=!0)})();return b};this.unsynched=function(b){a.synclist[b]&&(a.synclist[b]=!1)};this.css=function(b,g){for(var c in g)a.saved.css.push([b,c,b.css(c)]),b.css(c,g[c])};this.scrollTop=function(b){return"undefined"==typeof b?a.getScrollTop():a.setScrollTop(b)};this.scrollLeft=function(b){return"undefined"==typeof b?a.getScrollLeft():a.setScrollLeft(b)};var A=function(a,g,c,d,e,f,h){this.st=a;this.ed=g;this.spd=c;this.p1=
-d||0;this.p2=e||1;this.p3=f||0;this.p4=h||1;this.ts=(new Date).getTime();this.df=this.ed-this.st};A.prototype={B2:function(a){return 3*a*a*(1-a)},B3:function(a){return 3*a*(1-a)*(1-a)},B4:function(a){return(1-a)*(1-a)*(1-a)},getNow:function(){var a=1-((new Date).getTime()-this.ts)/this.spd,g=this.B2(a)+this.B3(a)+this.B4(a);return 0>a?this.ed:this.st+Math.round(this.df*g)},update:function(a,g){this.st=this.getNow();this.ed=a;this.spd=g;this.ts=(new Date).getTime();this.df=this.ed-this.st;return this}};
-if(this.ishwscroll){this.doc.translate={x:0,y:0,tx:"0px",ty:"0px"};e.hastranslate3d&&e.isios&&this.doc.css("-webkit-backface-visibility","hidden");this.getScrollTop=function(b){if(!b){if(b=h())return 16==b.length?-b[13]:-b[5];if(a.timerscroll&&a.timerscroll.bz)return a.timerscroll.bz.getNow()}return a.doc.translate.y};this.getScrollLeft=function(b){if(!b){if(b=h())return 16==b.length?-b[12]:-b[4];if(a.timerscroll&&a.timerscroll.bh)return a.timerscroll.bh.getNow()}return a.doc.translate.x};this.notifyScrollEvent=
-function(a){var g=document.createEvent("UIEvents");g.initUIEvent("scroll",!1,!0,window,1);g.niceevent=!0;a.dispatchEvent(g)};var K=this.isrtlmode?1:-1;e.hastranslate3d&&a.opt.enabletranslate3d?(this.setScrollTop=function(b,g){a.doc.translate.y=b;a.doc.translate.ty=-1*b+"px";a.doc.css(e.trstyle,"translate3d("+a.doc.translate.tx+","+a.doc.translate.ty+",0px)");g||a.notifyScrollEvent(a.win[0])},this.setScrollLeft=function(b,g){a.doc.translate.x=b;a.doc.translate.tx=b*K+"px";a.doc.css(e.trstyle,"translate3d("+
-a.doc.translate.tx+","+a.doc.translate.ty+",0px)");g||a.notifyScrollEvent(a.win[0])}):(this.setScrollTop=function(b,g){a.doc.translate.y=b;a.doc.translate.ty=-1*b+"px";a.doc.css(e.trstyle,"translate("+a.doc.translate.tx+","+a.doc.translate.ty+")");g||a.notifyScrollEvent(a.win[0])},this.setScrollLeft=function(b,g){a.doc.translate.x=b;a.doc.translate.tx=b*K+"px";a.doc.css(e.trstyle,"translate("+a.doc.translate.tx+","+a.doc.translate.ty+")");g||a.notifyScrollEvent(a.win[0])})}else this.getScrollTop=
-function(){return a.docscroll.scrollTop()},this.setScrollTop=function(b){return a.docscroll.scrollTop(b)},this.getScrollLeft=function(){return a.detected.ismozilla&&a.isrtlmode?Math.abs(a.docscroll.scrollLeft()):a.docscroll.scrollLeft()},this.setScrollLeft=function(b){return a.docscroll.scrollLeft(a.detected.ismozilla&&a.isrtlmode?-b:b)};this.getTarget=function(a){return a?a.target?a.target:a.srcElement?a.srcElement:!1:!1};this.hasParent=function(a,g){if(!a)return!1;for(var c=a.target||a.srcElement||
-a||!1;c&&c.id!=g;)c=c.parentNode||!1;return!1!==c};var w={thin:1,medium:3,thick:5};this.getDocumentScrollOffset=function(){return{top:window.pageYOffset||document.documentElement.scrollTop,left:window.pageXOffset||document.documentElement.scrollLeft}};this.getOffset=function(){if(a.isfixed){var b=a.win.offset(),g=a.getDocumentScrollOffset();b.top-=g.top;b.left-=g.left;return b}b=a.win.offset();if(!a.viewport)return b;g=a.viewport.offset();return{top:b.top-g.top,left:b.left-g.left}};this.updateScrollBar=
-function(b){if(a.ishwscroll)a.rail.css({height:a.win.innerHeight()-(a.opt.railpadding.top+a.opt.railpadding.bottom)}),a.railh&&a.railh.css({width:a.win.innerWidth()-(a.opt.railpadding.left+a.opt.railpadding.right)});else{var g=a.getOffset(),c=g.top,e=g.left-(a.opt.railpadding.left+a.opt.railpadding.right),c=c+d(a.win,"border-top-width",!0),e=e+(a.rail.align?a.win.outerWidth()-d(a.win,"border-right-width")-a.rail.width:d(a.win,"border-left-width")),f=a.opt.railoffset;f&&(f.top&&(c+=f.top),a.rail.align&&
-f.left&&(e+=f.left));a.railslocked||a.rail.css({top:c,left:e,height:(b?b.h:a.win.innerHeight())-(a.opt.railpadding.top+a.opt.railpadding.bottom)});a.zoom&&a.zoom.css({top:c+1,left:1==a.rail.align?e-20:e+a.rail.width+4});if(a.railh&&!a.railslocked){c=g.top;e=g.left;if(f=a.opt.railhoffset)f.top&&(c+=f.top),f.left&&(e+=f.left);b=a.railh.align?c+d(a.win,"border-top-width",!0)+a.win.innerHeight()-a.railh.height:c+d(a.win,"border-top-width",!0);e+=d(a.win,"border-left-width");a.railh.css({top:b-(a.opt.railpadding.top+
-a.opt.railpadding.bottom),left:e,width:a.railh.width})}}};this.doRailClick=function(b,g,c){var e;a.railslocked||(a.cancelEvent(b),g?(g=c?a.doScrollLeft:a.doScrollTop,e=c?(b.pageX-a.railh.offset().left-a.cursorwidth/2)*a.scrollratio.x:(b.pageY-a.rail.offset().top-a.cursorheight/2)*a.scrollratio.y,g(e)):(g=c?a.doScrollLeftBy:a.doScrollBy,e=c?a.scroll.x:a.scroll.y,b=c?b.pageX-a.railh.offset().left:b.pageY-a.rail.offset().top,c=c?a.view.w:a.view.h,g(e>=b?c:-c)))};a.hasanimationframe=s;a.hascancelanimationframe=
-t;a.hasanimationframe?a.hascancelanimationframe||(t=function(){a.cancelAnimationFrame=!0}):(s=function(a){return setTimeout(a,15-Math.floor(+new Date/1E3)%16)},t=clearInterval);this.init=function(){a.saved.css=[];if(e.isie7mobile||e.isoperamini)return!0;e.hasmstouch&&a.css(a.ispage?f("html"):a.win,{"-ms-touch-action":"none"});a.zindex="auto";a.zindex=a.ispage||"auto"!=a.opt.zindex?a.opt.zindex:m()||"auto";!a.ispage&&"auto"!=a.zindex&&a.zindex>x&&(x=a.zindex);a.isie&&0==a.zindex&&"auto"==a.opt.zindex&&
-(a.zindex="auto");if(!a.ispage||!e.cantouch&&!e.isieold&&!e.isie9mobile){var b=a.docscroll;a.ispage&&(b=a.haswrapper?a.win:a.doc);e.isie9mobile||a.css(b,{"overflow-y":"hidden"});a.ispage&&e.isie7&&("BODY"==a.doc[0].nodeName?a.css(f("html"),{"overflow-y":"hidden"}):"HTML"==a.doc[0].nodeName&&a.css(f("body"),{"overflow-y":"hidden"}));!e.isios||a.ispage||a.haswrapper||a.css(f("body"),{"-webkit-overflow-scrolling":"touch"});var g=f(document.createElement("div"));g.css({position:"relative",top:0,"float":"right",
-width:a.opt.cursorwidth,height:"0px","background-color":a.opt.cursorcolor,border:a.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":a.opt.cursorborderradius,"-moz-border-radius":a.opt.cursorborderradius,"border-radius":a.opt.cursorborderradius});g.hborder=parseFloat(g.outerHeight()-g.innerHeight());g.addClass("nicescroll-cursors");a.cursor=g;var c=f(document.createElement("div"));c.attr("id",a.id);c.addClass("nicescroll-rails nicescroll-rails-vr");var d,h,k=["left","right",
-"top","bottom"],J;for(J in k)h=k[J],(d=a.opt.railpadding[h])?c.css("padding-"+h,d+"px"):a.opt.railpadding[h]=0;c.append(g);c.width=Math.max(parseFloat(a.opt.cursorwidth),g.outerWidth());c.css({width:c.width+"px",zIndex:a.zindex,background:a.opt.background,cursor:"default"});c.visibility=!0;c.scrollable=!0;c.align="left"==a.opt.railalign?0:1;a.rail=c;g=a.rail.drag=!1;!a.opt.boxzoom||a.ispage||e.isieold||(g=document.createElement("div"),a.bind(g,"click",a.doZoom),a.bind(g,"mouseenter",function(){a.zoom.css("opacity",
-a.opt.cursoropacitymax)}),a.bind(g,"mouseleave",function(){a.zoom.css("opacity",a.opt.cursoropacitymin)}),a.zoom=f(g),a.zoom.css({cursor:"pointer","z-index":a.zindex,backgroundImage:"url("+a.opt.scriptpath+"zoomico.png)",height:18,width:18,backgroundPosition:"0px 0px"}),a.opt.dblclickzoom&&a.bind(a.win,"dblclick",a.doZoom),e.cantouch&&a.opt.gesturezoom&&(a.ongesturezoom=function(b){1.5<b.scale&&a.doZoomIn(b);.8>b.scale&&a.doZoomOut(b);return a.cancelEvent(b)},a.bind(a.win,"gestureend",a.ongesturezoom)));
-a.railh=!1;var l;a.opt.horizrailenabled&&(a.css(b,{"overflow-x":"hidden"}),g=f(document.createElement("div")),g.css({position:"absolute",top:0,height:a.opt.cursorwidth,width:"0px","background-color":a.opt.cursorcolor,border:a.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":a.opt.cursorborderradius,"-moz-border-radius":a.opt.cursorborderradius,"border-radius":a.opt.cursorborderradius}),e.isieold&&g.css({overflow:"hidden"}),g.wborder=parseFloat(g.outerWidth()-g.innerWidth()),
-g.addClass("nicescroll-cursors"),a.cursorh=g,l=f(document.createElement("div")),l.attr("id",a.id+"-hr"),l.addClass("nicescroll-rails nicescroll-rails-hr"),l.height=Math.max(parseFloat(a.opt.cursorwidth),g.outerHeight()),l.css({height:l.height+"px",zIndex:a.zindex,background:a.opt.background}),l.append(g),l.visibility=!0,l.scrollable=!0,l.align="top"==a.opt.railvalign?0:1,a.railh=l,a.railh.drag=!1);a.ispage?(c.css({position:"fixed",top:"0px",height:"100%"}),c.align?c.css({right:"0px"}):c.css({left:"0px"}),
-a.body.append(c),a.railh&&(l.css({position:"fixed",left:"0px",width:"100%"}),l.align?l.css({bottom:"0px"}):l.css({top:"0px"}),a.body.append(l))):(a.ishwscroll?("static"==a.win.css("position")&&a.css(a.win,{position:"relative"}),b="HTML"==a.win[0].nodeName?a.body:a.win,f(b).scrollTop(0).scrollLeft(0),a.zoom&&(a.zoom.css({position:"absolute",top:1,right:0,"margin-right":c.width+4}),b.append(a.zoom)),c.css({position:"absolute",top:0}),c.align?c.css({right:0}):c.css({left:0}),b.append(c),l&&(l.css({position:"absolute",
-left:0,bottom:0}),l.align?l.css({bottom:0}):l.css({top:0}),b.append(l))):(a.isfixed="fixed"==a.win.css("position"),b=a.isfixed?"fixed":"absolute",a.isfixed||(a.viewport=a.getViewport(a.win[0])),a.viewport&&(a.body=a.viewport,0==/fixed|absolute/.test(a.viewport.css("position"))&&a.css(a.viewport,{position:"relative"})),c.css({position:b}),a.zoom&&a.zoom.css({position:b}),a.updateScrollBar(),a.body.append(c),a.zoom&&a.body.append(a.zoom),a.railh&&(l.css({position:b}),a.body.append(l))),e.isios&&a.css(a.win,
-{"-webkit-tap-highlight-color":"rgba(0,0,0,0)","-webkit-touch-callout":"none"}),e.isie&&a.opt.disableoutline&&a.win.attr("hideFocus","true"),e.iswebkit&&a.opt.disableoutline&&a.win.css({outline:"none"}));!1===a.opt.autohidemode?(a.autohidedom=!1,a.rail.css({opacity:a.opt.cursoropacitymax}),a.railh&&a.railh.css({opacity:a.opt.cursoropacitymax})):!0===a.opt.autohidemode||"leave"===a.opt.autohidemode?(a.autohidedom=f().add(a.rail),e.isie8&&(a.autohidedom=a.autohidedom.add(a.cursor)),a.railh&&(a.autohidedom=
-a.autohidedom.add(a.railh)),a.railh&&e.isie8&&(a.autohidedom=a.autohidedom.add(a.cursorh))):"scroll"==a.opt.autohidemode?(a.autohidedom=f().add(a.rail),a.railh&&(a.autohidedom=a.autohidedom.add(a.railh))):"cursor"==a.opt.autohidemode?(a.autohidedom=f().add(a.cursor),a.railh&&(a.autohidedom=a.autohidedom.add(a.cursorh))):"hidden"==a.opt.autohidemode&&(a.autohidedom=!1,a.hide(),a.railslocked=!1);if(e.isie9mobile)a.scrollmom=new L(a),a.onmangotouch=function(){var b=a.getScrollTop(),c=a.getScrollLeft();
-if(b==a.scrollmom.lastscrolly&&c==a.scrollmom.lastscrollx)return!0;var g=b-a.mangotouch.sy,e=c-a.mangotouch.sx;if(0!=Math.round(Math.sqrt(Math.pow(e,2)+Math.pow(g,2)))){var d=0>g?-1:1,f=0>e?-1:1,q=+new Date;a.mangotouch.lazy&&clearTimeout(a.mangotouch.lazy);80<q-a.mangotouch.tm||a.mangotouch.dry!=d||a.mangotouch.drx!=f?(a.scrollmom.stop(),a.scrollmom.reset(c,b),a.mangotouch.sy=b,a.mangotouch.ly=b,a.mangotouch.sx=c,a.mangotouch.lx=c,a.mangotouch.dry=d,a.mangotouch.drx=f,a.mangotouch.tm=q):(a.scrollmom.stop(),
-a.scrollmom.update(a.mangotouch.sx-e,a.mangotouch.sy-g),a.mangotouch.tm=q,g=Math.max(Math.abs(a.mangotouch.ly-b),Math.abs(a.mangotouch.lx-c)),a.mangotouch.ly=b,a.mangotouch.lx=c,2<g&&(a.mangotouch.lazy=setTimeout(function(){a.mangotouch.lazy=!1;a.mangotouch.dry=0;a.mangotouch.drx=0;a.mangotouch.tm=0;a.scrollmom.doMomentum(30)},100)))}},c=a.getScrollTop(),l=a.getScrollLeft(),a.mangotouch={sy:c,ly:c,dry:0,sx:l,lx:l,drx:0,lazy:!1,tm:0},a.bind(a.docscroll,"scroll",a.onmangotouch);else{if(e.cantouch||
-a.istouchcapable||a.opt.touchbehavior||e.hasmstouch){a.scrollmom=new L(a);a.ontouchstart=function(b){if(b.pointerType&&2!=b.pointerType&&"touch"!=b.pointerType)return!1;a.hasmoving=!1;if(!a.railslocked){var c;if(e.hasmstouch)for(c=b.target?b.target:!1;c;){var g=f(c).getNiceScroll();if(0<g.length&&g[0].me==a.me)break;if(0<g.length)return!1;if("DIV"==c.nodeName&&c.id==a.id)break;c=c.parentNode?c.parentNode:!1}a.cancelScroll();if((c=a.getTarget(b))&&/INPUT/i.test(c.nodeName)&&/range/i.test(c.type))return a.stopPropagation(b);
-!("clientX"in b)&&"changedTouches"in b&&(b.clientX=b.changedTouches[0].clientX,b.clientY=b.changedTouches[0].clientY);a.forcescreen&&(g=b,b={original:b.original?b.original:b},b.clientX=g.screenX,b.clientY=g.screenY);a.rail.drag={x:b.clientX,y:b.clientY,sx:a.scroll.x,sy:a.scroll.y,st:a.getScrollTop(),sl:a.getScrollLeft(),pt:2,dl:!1};if(a.ispage||!a.opt.directionlockdeadzone)a.rail.drag.dl="f";else{var g=f(window).width(),d=f(window).height(),q=Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),
-h=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight),d=Math.max(0,h-d),g=Math.max(0,q-g);a.rail.drag.ck=!a.rail.scrollable&&a.railh.scrollable?0<d?"v":!1:a.rail.scrollable&&!a.railh.scrollable?0<g?"h":!1:!1;a.rail.drag.ck||(a.rail.drag.dl="f")}a.opt.touchbehavior&&a.isiframe&&e.isie&&(g=a.win.position(),a.rail.drag.x+=g.left,a.rail.drag.y+=g.top);a.hasmoving=!1;a.lastmouseup=!1;a.scrollmom.reset(b.clientX,b.clientY);if(!e.cantouch&&!this.istouchcapable&&!b.pointerType){if(!c||
-!/INPUT|SELECT|TEXTAREA/i.test(c.nodeName))return!a.ispage&&e.hasmousecapture&&c.setCapture(),a.opt.touchbehavior?(c.onclick&&!c._onclick&&(c._onclick=c.onclick,c.onclick=function(b){if(a.hasmoving)return!1;c._onclick.call(this,b)}),a.cancelEvent(b)):a.stopPropagation(b);/SUBMIT|CANCEL|BUTTON/i.test(f(c).attr("type"))&&(pc={tg:c,click:!1},a.preventclick=pc)}}};a.ontouchend=function(b){if(!a.rail.drag)return!0;if(2==a.rail.drag.pt){if(b.pointerType&&2!=b.pointerType&&"touch"!=b.pointerType)return!1;
-a.scrollmom.doMomentum();a.rail.drag=!1;if(a.hasmoving&&(a.lastmouseup=!0,a.hideCursor(),e.hasmousecapture&&document.releaseCapture(),!e.cantouch))return a.cancelEvent(b)}else if(1==a.rail.drag.pt)return a.onmouseup(b)};var n=a.opt.touchbehavior&&a.isiframe&&!e.hasmousecapture;a.ontouchmove=function(b,c){if(!a.rail.drag||b.targetTouches&&a.opt.preventmultitouchscrolling&&1<b.targetTouches.length||b.pointerType&&2!=b.pointerType&&"touch"!=b.pointerType)return!1;if(2==a.rail.drag.pt){if(e.cantouch&&
-e.isios&&"undefined"==typeof b.original)return!0;a.hasmoving=!0;a.preventclick&&!a.preventclick.click&&(a.preventclick.click=a.preventclick.tg.onclick||!1,a.preventclick.tg.onclick=a.onpreventclick);b=f.extend({original:b},b);"changedTouches"in b&&(b.clientX=b.changedTouches[0].clientX,b.clientY=b.changedTouches[0].clientY);if(a.forcescreen){var g=b;b={original:b.original?b.original:b};b.clientX=g.screenX;b.clientY=g.screenY}var d,g=d=0;n&&!c&&(d=a.win.position(),g=-d.left,d=-d.top);var q=b.clientY+
-d;d=q-a.rail.drag.y;var h=b.clientX+g,u=h-a.rail.drag.x,k=a.rail.drag.st-d;a.ishwscroll&&a.opt.bouncescroll?0>k?k=Math.round(k/2):k>a.page.maxh&&(k=a.page.maxh+Math.round((k-a.page.maxh)/2)):(0>k&&(q=k=0),k>a.page.maxh&&(k=a.page.maxh,q=0));var l;a.railh&&a.railh.scrollable&&(l=a.isrtlmode?u-a.rail.drag.sl:a.rail.drag.sl-u,a.ishwscroll&&a.opt.bouncescroll?0>l?l=Math.round(l/2):l>a.page.maxw&&(l=a.page.maxw+Math.round((l-a.page.maxw)/2)):(0>l&&(h=l=0),l>a.page.maxw&&(l=a.page.maxw,h=0)));g=!1;if(a.rail.drag.dl)g=
-!0,"v"==a.rail.drag.dl?l=a.rail.drag.sl:"h"==a.rail.drag.dl&&(k=a.rail.drag.st);else{d=Math.abs(d);var u=Math.abs(u),z=a.opt.directionlockdeadzone;if("v"==a.rail.drag.ck){if(d>z&&u<=.3*d)return a.rail.drag=!1,!0;u>z&&(a.rail.drag.dl="f",f("body").scrollTop(f("body").scrollTop()))}else if("h"==a.rail.drag.ck){if(u>z&&d<=.3*u)return a.rail.drag=!1,!0;d>z&&(a.rail.drag.dl="f",f("body").scrollLeft(f("body").scrollLeft()))}}a.synched("touchmove",function(){a.rail.drag&&2==a.rail.drag.pt&&(a.prepareTransition&&
-a.prepareTransition(0),a.rail.scrollable&&a.setScrollTop(k),a.scrollmom.update(h,q),a.railh&&a.railh.scrollable?(a.setScrollLeft(l),a.showCursor(k,l)):a.showCursor(k),e.isie10&&document.selection.clear())});e.ischrome&&a.istouchcapable&&(g=!1);if(g)return a.cancelEvent(b)}else if(1==a.rail.drag.pt)return a.onmousemove(b)}}a.onmousedown=function(b,c){if(!a.rail.drag||1==a.rail.drag.pt){if(a.railslocked)return a.cancelEvent(b);a.cancelScroll();a.rail.drag={x:b.clientX,y:b.clientY,sx:a.scroll.x,sy:a.scroll.y,
-pt:1,hr:!!c};var g=a.getTarget(b);!a.ispage&&e.hasmousecapture&&g.setCapture();a.isiframe&&!e.hasmousecapture&&(a.saved.csspointerevents=a.doc.css("pointer-events"),a.css(a.doc,{"pointer-events":"none"}));a.hasmoving=!1;return a.cancelEvent(b)}};a.onmouseup=function(b){if(a.rail.drag){if(1!=a.rail.drag.pt)return!0;e.hasmousecapture&&document.releaseCapture();a.isiframe&&!e.hasmousecapture&&a.doc.css("pointer-events",a.saved.csspointerevents);a.rail.drag=!1;a.hasmoving&&a.triggerScrollEnd();return a.cancelEvent(b)}};
-a.onmousemove=function(b){if(a.rail.drag&&1==a.rail.drag.pt){if(e.ischrome&&0==b.which)return a.onmouseup(b);a.cursorfreezed=!0;a.hasmoving=!0;if(a.rail.drag.hr){a.scroll.x=a.rail.drag.sx+(b.clientX-a.rail.drag.x);0>a.scroll.x&&(a.scroll.x=0);var c=a.scrollvaluemaxw;a.scroll.x>c&&(a.scroll.x=c)}else a.scroll.y=a.rail.drag.sy+(b.clientY-a.rail.drag.y),0>a.scroll.y&&(a.scroll.y=0),c=a.scrollvaluemax,a.scroll.y>c&&(a.scroll.y=c);a.synched("mousemove",function(){a.rail.drag&&1==a.rail.drag.pt&&(a.showCursor(),
-a.rail.drag.hr?a.hasreversehr?a.doScrollLeft(a.scrollvaluemaxw-Math.round(a.scroll.x*a.scrollratio.x),a.opt.cursordragspeed):a.doScrollLeft(Math.round(a.scroll.x*a.scrollratio.x),a.opt.cursordragspeed):a.doScrollTop(Math.round(a.scroll.y*a.scrollratio.y),a.opt.cursordragspeed))});return a.cancelEvent(b)}};if(e.cantouch||a.opt.touchbehavior)a.onpreventclick=function(b){if(a.preventclick)return a.preventclick.tg.onclick=a.preventclick.click,a.preventclick=!1,a.cancelEvent(b)},a.bind(a.win,"mousedown",
-a.ontouchstart),a.onclick=e.isios?!1:function(b){return a.lastmouseup?(a.lastmouseup=!1,a.cancelEvent(b)):!0},a.opt.grabcursorenabled&&e.cursorgrabvalue&&(a.css(a.ispage?a.doc:a.win,{cursor:e.cursorgrabvalue}),a.css(a.rail,{cursor:e.cursorgrabvalue}));else{var p=function(b){if(a.selectiondrag){if(b){var c=a.win.outerHeight();b=b.pageY-a.selectiondrag.top;0<b&&b<c&&(b=0);b>=c&&(b-=c);a.selectiondrag.df=b}0!=a.selectiondrag.df&&(a.doScrollBy(2*-Math.floor(a.selectiondrag.df/6)),a.debounced("doselectionscroll",
-function(){p()},50))}};a.hasTextSelected="getSelection"in document?function(){return 0<document.getSelection().rangeCount}:"selection"in document?function(){return"None"!=document.selection.type}:function(){return!1};a.onselectionstart=function(b){a.ispage||(a.selectiondrag=a.win.offset())};a.onselectionend=function(b){a.selectiondrag=!1};a.onselectiondrag=function(b){a.selectiondrag&&a.hasTextSelected()&&a.debounced("selectionscroll",function(){p(b)},250)}}e.hasw3ctouch?(a.css(a.rail,{"touch-action":"none"}),
-a.css(a.cursor,{"touch-action":"none"}),a.bind(a.win,"pointerdown",a.ontouchstart),a.bind(document,"pointerup",a.ontouchend),a.bind(document,"pointermove",a.ontouchmove)):e.hasmstouch?(a.css(a.rail,{"-ms-touch-action":"none"}),a.css(a.cursor,{"-ms-touch-action":"none"}),a.bind(a.win,"MSPointerDown",a.ontouchstart),a.bind(document,"MSPointerUp",a.ontouchend),a.bind(document,"MSPointerMove",a.ontouchmove),a.bind(a.cursor,"MSGestureHold",function(a){a.preventDefault()}),a.bind(a.cursor,"contextmenu",
-function(a){a.preventDefault()})):this.istouchcapable&&(a.bind(a.win,"touchstart",a.ontouchstart),a.bind(document,"touchend",a.ontouchend),a.bind(document,"touchcancel",a.ontouchend),a.bind(document,"touchmove",a.ontouchmove));if(a.opt.cursordragontouch||!e.cantouch&&!a.opt.touchbehavior)a.rail.css({cursor:"default"}),a.railh&&a.railh.css({cursor:"default"}),a.jqbind(a.rail,"mouseenter",function(){if(!a.ispage&&!a.win.is(":visible"))return!1;a.canshowonmouseevent&&a.showCursor();a.rail.active=!0}),
-a.jqbind(a.rail,"mouseleave",function(){a.rail.active=!1;a.rail.drag||a.hideCursor()}),a.opt.sensitiverail&&(a.bind(a.rail,"click",function(b){a.doRailClick(b,!1,!1)}),a.bind(a.rail,"dblclick",function(b){a.doRailClick(b,!0,!1)}),a.bind(a.cursor,"click",function(b){a.cancelEvent(b)}),a.bind(a.cursor,"dblclick",function(b){a.cancelEvent(b)})),a.railh&&(a.jqbind(a.railh,"mouseenter",function(){if(!a.ispage&&!a.win.is(":visible"))return!1;a.canshowonmouseevent&&a.showCursor();a.rail.active=!0}),a.jqbind(a.railh,
-"mouseleave",function(){a.rail.active=!1;a.rail.drag||a.hideCursor()}),a.opt.sensitiverail&&(a.bind(a.railh,"click",function(b){a.doRailClick(b,!1,!0)}),a.bind(a.railh,"dblclick",function(b){a.doRailClick(b,!0,!0)}),a.bind(a.cursorh,"click",function(b){a.cancelEvent(b)}),a.bind(a.cursorh,"dblclick",function(b){a.cancelEvent(b)})));e.cantouch||a.opt.touchbehavior?(a.bind(e.hasmousecapture?a.win:document,"mouseup",a.ontouchend),a.bind(document,"mousemove",a.ontouchmove),a.onclick&&a.bind(document,"click",
-a.onclick),a.opt.cursordragontouch&&(a.bind(a.cursor,"mousedown",a.onmousedown),a.bind(a.cursor,"mouseup",a.onmouseup),a.cursorh&&a.bind(a.cursorh,"mousedown",function(b){a.onmousedown(b,!0)}),a.cursorh&&a.bind(a.cursorh,"mouseup",a.onmouseup))):(a.bind(e.hasmousecapture?a.win:document,"mouseup",a.onmouseup),a.bind(document,"mousemove",a.onmousemove),a.onclick&&a.bind(document,"click",a.onclick),a.bind(a.cursor,"mousedown",a.onmousedown),a.bind(a.cursor,"mouseup",a.onmouseup),a.railh&&(a.bind(a.cursorh,
-"mousedown",function(b){a.onmousedown(b,!0)}),a.bind(a.cursorh,"mouseup",a.onmouseup)),!a.ispage&&a.opt.enablescrollonselection&&(a.bind(a.win[0],"mousedown",a.onselectionstart),a.bind(document,"mouseup",a.onselectionend),a.bind(a.cursor,"mouseup",a.onselectionend),a.cursorh&&a.bind(a.cursorh,"mouseup",a.onselectionend),a.bind(document,"mousemove",a.onselectiondrag)),a.zoom&&(a.jqbind(a.zoom,"mouseenter",function(){a.canshowonmouseevent&&a.showCursor();a.rail.active=!0}),a.jqbind(a.zoom,"mouseleave",
-function(){a.rail.active=!1;a.rail.drag||a.hideCursor()})));a.opt.enablemousewheel&&(a.isiframe||a.bind(e.isie&&a.ispage?document:a.win,"mousewheel",a.onmousewheel),a.bind(a.rail,"mousewheel",a.onmousewheel),a.railh&&a.bind(a.railh,"mousewheel",a.onmousewheelhr));a.ispage||e.cantouch||/HTML|^BODY/.test(a.win[0].nodeName)||(a.win.attr("tabindex")||a.win.attr({tabindex:N++}),a.jqbind(a.win,"focus",function(b){y=a.getTarget(b).id||!0;a.hasfocus=!0;a.canshowonmouseevent&&a.noticeCursor()}),a.jqbind(a.win,
-"blur",function(b){y=!1;a.hasfocus=!1}),a.jqbind(a.win,"mouseenter",function(b){D=a.getTarget(b).id||!0;a.hasmousefocus=!0;a.canshowonmouseevent&&a.noticeCursor()}),a.jqbind(a.win,"mouseleave",function(){D=!1;a.hasmousefocus=!1;a.rail.drag||a.hideCursor()}))}a.onkeypress=function(b){if(a.railslocked&&0==a.page.maxh)return!0;b=b?b:window.e;var c=a.getTarget(b);if(c&&/INPUT|TEXTAREA|SELECT|OPTION/.test(c.nodeName)&&(!c.getAttribute("type")&&!c.type||!/submit|button|cancel/i.tp)||f(c).attr("contenteditable"))return!0;
-if(a.hasfocus||a.hasmousefocus&&!y||a.ispage&&!y&&!D){c=b.keyCode;if(a.railslocked&&27!=c)return a.cancelEvent(b);var g=b.ctrlKey||!1,d=b.shiftKey||!1,e=!1;switch(c){case 38:case 63233:a.doScrollBy(72);e=!0;break;case 40:case 63235:a.doScrollBy(-72);e=!0;break;case 37:case 63232:a.railh&&(g?a.doScrollLeft(0):a.doScrollLeftBy(72),e=!0);break;case 39:case 63234:a.railh&&(g?a.doScrollLeft(a.page.maxw):a.doScrollLeftBy(-72),e=!0);break;case 33:case 63276:a.doScrollBy(a.view.h);e=!0;break;case 34:case 63277:a.doScrollBy(-a.view.h);
-e=!0;break;case 36:case 63273:a.railh&&g?a.doScrollPos(0,0):a.doScrollTo(0);e=!0;break;case 35:case 63275:a.railh&&g?a.doScrollPos(a.page.maxw,a.page.maxh):a.doScrollTo(a.page.maxh);e=!0;break;case 32:a.opt.spacebarenabled&&(d?a.doScrollBy(a.view.h):a.doScrollBy(-a.view.h),e=!0);break;case 27:a.zoomactive&&(a.doZoom(),e=!0)}if(e)return a.cancelEvent(b)}};a.opt.enablekeyboard&&a.bind(document,e.isopera&&!e.isopera12?"keypress":"keydown",a.onkeypress);a.bind(document,"keydown",function(b){b.ctrlKey&&
-(a.wheelprevented=!0)});a.bind(document,"keyup",function(b){b.ctrlKey||(a.wheelprevented=!1)});a.bind(window,"blur",function(b){a.wheelprevented=!1});a.bind(window,"resize",a.lazyResize);a.bind(window,"orientationchange",a.lazyResize);a.bind(window,"load",a.lazyResize);if(e.ischrome&&!a.ispage&&!a.haswrapper){var r=a.win.attr("style"),c=parseFloat(a.win.css("width"))+1;a.win.css("width",c);a.synched("chromefix",function(){a.win.attr("style",r)})}a.onAttributeChange=function(b){a.lazyResize(a.isieold?
-250:30)};!1!==v&&(a.observerbody=new v(function(b){b.forEach(function(b){if("attributes"==b.type)return f("body").hasClass("modal-open")?a.hide():a.show()});if(document.body.scrollHeight!=a.page.maxh)return a.lazyResize(30)}),a.observerbody.observe(document.body,{childList:!0,subtree:!0,characterData:!1,attributes:!0,attributeFilter:["class"]}));a.ispage||a.haswrapper||(!1!==v?(a.observer=new v(function(b){b.forEach(a.onAttributeChange)}),a.observer.observe(a.win[0],{childList:!0,characterData:!1,
-attributes:!0,subtree:!1}),a.observerremover=new v(function(b){b.forEach(function(b){if(0<b.removedNodes.length)for(var c in b.removedNodes)if(a&&b.removedNodes[c]==a.win[0])return a.remove()})}),a.observerremover.observe(a.win[0].parentNode,{childList:!0,characterData:!1,attributes:!1,subtree:!1})):(a.bind(a.win,e.isie&&!e.isie9?"propertychange":"DOMAttrModified",a.onAttributeChange),e.isie9&&a.win[0].attachEvent("onpropertychange",a.onAttributeChange),a.bind(a.win,"DOMNodeRemoved",function(b){b.target==
-a.win[0]&&a.remove()})));!a.ispage&&a.opt.boxzoom&&a.bind(window,"resize",a.resizeZoom);a.istextarea&&a.bind(a.win,"mouseup",a.lazyResize);a.lazyResize(30)}if("IFRAME"==this.doc[0].nodeName){var M=function(){a.iframexd=!1;var b;try{b="contentDocument"in this?this.contentDocument:this.contentWindow.document}catch(c){a.iframexd=!0,b=!1}if(a.iframexd)return"console"in window&&console.log("NiceScroll error: policy restriced iframe"),!0;a.forcescreen=!0;a.isiframe&&(a.iframe={doc:f(b),html:a.doc.contents().find("html")[0],
-body:a.doc.contents().find("body")[0]},a.getContentSize=function(){return{w:Math.max(a.iframe.html.scrollWidth,a.iframe.body.scrollWidth),h:Math.max(a.iframe.html.scrollHeight,a.iframe.body.scrollHeight)}},a.docscroll=f(a.iframe.body));if(!e.isios&&a.opt.iframeautoresize&&!a.isiframe){a.win.scrollTop(0);a.doc.height("");var g=Math.max(b.getElementsByTagName("html")[0].scrollHeight,b.body.scrollHeight);a.doc.height(g)}a.lazyResize(30);e.isie7&&a.css(f(a.iframe.html),{"overflow-y":"hidden"});a.css(f(a.iframe.body),
-{"overflow-y":"hidden"});e.isios&&a.haswrapper&&a.css(f(b.body),{"-webkit-transform":"translate3d(0,0,0)"});"contentWindow"in this?a.bind(this.contentWindow,"scroll",a.onscroll):a.bind(b,"scroll",a.onscroll);a.opt.enablemousewheel&&a.bind(b,"mousewheel",a.onmousewheel);a.opt.enablekeyboard&&a.bind(b,e.isopera?"keypress":"keydown",a.onkeypress);if(e.cantouch||a.opt.touchbehavior)a.bind(b,"mousedown",a.ontouchstart),a.bind(b,"mousemove",function(b){return a.ontouchmove(b,!0)}),a.opt.grabcursorenabled&&
-e.cursorgrabvalue&&a.css(f(b.body),{cursor:e.cursorgrabvalue});a.bind(b,"mouseup",a.ontouchend);a.zoom&&(a.opt.dblclickzoom&&a.bind(b,"dblclick",a.doZoom),a.ongesturezoom&&a.bind(b,"gestureend",a.ongesturezoom))};this.doc[0].readyState&&"complete"==this.doc[0].readyState&&setTimeout(function(){M.call(a.doc[0],!1)},500);a.bind(this.doc,"load",M)}};this.showCursor=function(b,c){a.cursortimeout&&(clearTimeout(a.cursortimeout),a.cursortimeout=0);if(a.rail){a.autohidedom&&(a.autohidedom.stop().css({opacity:a.opt.cursoropacitymax}),
-a.cursoractive=!0);a.rail.drag&&1==a.rail.drag.pt||("undefined"!=typeof b&&!1!==b&&(a.scroll.y=Math.round(1*b/a.scrollratio.y)),"undefined"!=typeof c&&(a.scroll.x=Math.round(1*c/a.scrollratio.x)));a.cursor.css({height:a.cursorheight,top:a.scroll.y});if(a.cursorh){var d=a.hasreversehr?a.scrollvaluemaxw-a.scroll.x:a.scroll.x;!a.rail.align&&a.rail.visibility?a.cursorh.css({width:a.cursorwidth,left:d+a.rail.width}):a.cursorh.css({width:a.cursorwidth,left:d});a.cursoractive=!0}a.zoom&&a.zoom.stop().css({opacity:a.opt.cursoropacitymax})}};
-this.hideCursor=function(b){a.cursortimeout||!a.rail||!a.autohidedom||a.hasmousefocus&&"leave"==a.opt.autohidemode||(a.cursortimeout=setTimeout(function(){a.rail.active&&a.showonmouseevent||(a.autohidedom.stop().animate({opacity:a.opt.cursoropacitymin}),a.zoom&&a.zoom.stop().animate({opacity:a.opt.cursoropacitymin}),a.cursoractive=!1);a.cursortimeout=0},b||a.opt.hidecursordelay))};this.noticeCursor=function(b,c,d){a.showCursor(c,d);a.rail.active||a.hideCursor(b)};this.getContentSize=a.ispage?function(){return{w:Math.max(document.body.scrollWidth,
-document.documentElement.scrollWidth),h:Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}}:a.haswrapper?function(){return{w:a.doc.outerWidth()+parseInt(a.win.css("paddingLeft"))+parseInt(a.win.css("paddingRight")),h:a.doc.outerHeight()+parseInt(a.win.css("paddingTop"))+parseInt(a.win.css("paddingBottom"))}}:function(){return{w:a.docscroll[0].scrollWidth,h:a.docscroll[0].scrollHeight}};this.onResize=function(b,c){if(!a||!a.win)return!1;if(!a.haswrapper&&!a.ispage){if("none"==
-a.win.css("display"))return a.visibility&&a.hideRail().hideRailHr(),!1;a.hidden||a.visibility||a.showRail().showRailHr()}var d=a.page.maxh,e=a.page.maxw,f=a.view.h,h=a.view.w;a.view={w:a.ispage?a.win.width():parseInt(a.win[0].clientWidth),h:a.ispage?a.win.height():parseInt(a.win[0].clientHeight)};a.page=c?c:a.getContentSize();a.page.maxh=Math.max(0,a.page.h-a.view.h);a.page.maxw=Math.max(0,a.page.w-a.view.w);if(a.page.maxh==d&&a.page.maxw==e&&a.view.w==h&&a.view.h==f){if(a.ispage)return a;d=a.win.offset();
-if(a.lastposition&&(e=a.lastposition,e.top==d.top&&e.left==d.left))return a;a.lastposition=d}0==a.page.maxh?(a.hideRail(),a.scrollvaluemax=0,a.scroll.y=0,a.scrollratio.y=0,a.cursorheight=0,a.setScrollTop(0),a.rail.scrollable=!1):(a.page.maxh-=a.opt.railpadding.top+a.opt.railpadding.bottom,a.rail.scrollable=!0);0==a.page.maxw?(a.hideRailHr(),a.scrollvaluemaxw=0,a.scroll.x=0,a.scrollratio.x=0,a.cursorwidth=0,a.setScrollLeft(0),a.railh.scrollable=!1):(a.page.maxw-=a.opt.railpadding.left+a.opt.railpadding.right,
-a.railh.scrollable=!0);a.railslocked=a.locked||0==a.page.maxh&&0==a.page.maxw;if(a.railslocked)return a.ispage||a.updateScrollBar(a.view),!1;a.hidden||a.visibility?a.hidden||a.railh.visibility||a.showRailHr():a.showRail().showRailHr();a.istextarea&&a.win.css("resize")&&"none"!=a.win.css("resize")&&(a.view.h-=20);a.cursorheight=Math.min(a.view.h,Math.round(a.view.h/a.page.h*a.view.h));a.cursorheight=a.opt.cursorfixedheight?a.opt.cursorfixedheight:Math.max(a.opt.cursorminheight,a.cursorheight);a.cursorwidth=
-Math.min(a.view.w,Math.round(a.view.w/a.page.w*a.view.w));a.cursorwidth=a.opt.cursorfixedheight?a.opt.cursorfixedheight:Math.max(a.opt.cursorminheight,a.cursorwidth);a.scrollvaluemax=a.view.h-a.cursorheight-a.cursor.hborder-(a.opt.railpadding.top+a.opt.railpadding.bottom);a.railh&&(a.railh.width=0<a.page.maxh?a.view.w-a.rail.width:a.view.w,a.scrollvaluemaxw=a.railh.width-a.cursorwidth-a.cursorh.wborder-(a.opt.railpadding.left+a.opt.railpadding.right));a.ispage||a.updateScrollBar(a.view);a.scrollratio=
-{x:a.page.maxw/a.scrollvaluemaxw,y:a.page.maxh/a.scrollvaluemax};a.getScrollTop()>a.page.maxh?a.doScrollTop(a.page.maxh):(a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y)),a.scroll.x=Math.round(a.getScrollLeft()*(1/a.scrollratio.x)),a.cursoractive&&a.noticeCursor());a.scroll.y&&0==a.getScrollTop()&&a.doScrollTo(Math.floor(a.scroll.y*a.scrollratio.y));return a};this.resize=a.onResize;this.lazyResize=function(b){b=isNaN(b)?30:b;a.debounced("resize",a.resize,b);return a};this.jqbind=function(b,
-c,d){a.events.push({e:b,n:c,f:d,q:!0});f(b).bind(c,d)};this.bind=function(b,c,d,f){var h="jquery"in b?b[0]:b;"mousewheel"==c?window.addEventListener||"onwheel"in document?a._bind(h,"wheel",d,f||!1):(b="undefined"!=typeof document.onmousewheel?"mousewheel":"DOMMouseScroll",n(h,b,d,f||!1),"DOMMouseScroll"==b&&n(h,"MozMousePixelScroll",d,f||!1)):h.addEventListener?(e.cantouch&&/mouseup|mousedown|mousemove/.test(c)&&a._bind(h,"mousedown"==c?"touchstart":"mouseup"==c?"touchend":"touchmove",function(a){if(a.touches){if(2>
-a.touches.length){var b=a.touches.length?a.touches[0]:a;b.original=a;d.call(this,b)}}else a.changedTouches&&(b=a.changedTouches[0],b.original=a,d.call(this,b))},f||!1),a._bind(h,c,d,f||!1),e.cantouch&&"mouseup"==c&&a._bind(h,"touchcancel",d,f||!1)):a._bind(h,c,function(b){(b=b||window.event||!1)&&b.srcElement&&(b.target=b.srcElement);"pageY"in b||(b.pageX=b.clientX+document.documentElement.scrollLeft,b.pageY=b.clientY+document.documentElement.scrollTop);return!1===d.call(h,b)||!1===f?a.cancelEvent(b):
-!0})};e.haseventlistener?(this._bind=function(b,c,d,e){a.events.push({e:b,n:c,f:d,b:e,q:!1});b.addEventListener(c,d,e||!1)},this.cancelEvent=function(a){if(!a)return!1;a=a.original?a.original:a;a.preventDefault();a.stopPropagation();a.preventManipulation&&a.preventManipulation();return!1},this.stopPropagation=function(a){if(!a)return!1;a=a.original?a.original:a;a.stopPropagation();return!1},this._unbind=function(a,c,d,e){a.removeEventListener(c,d,e)}):(this._bind=function(b,c,d,e){a.events.push({e:b,
-n:c,f:d,b:e,q:!1});b.attachEvent?b.attachEvent("on"+c,d):b["on"+c]=d},this.cancelEvent=function(a){a=window.event||!1;if(!a)return!1;a.cancelBubble=!0;a.cancel=!0;return a.returnValue=!1},this.stopPropagation=function(a){a=window.event||!1;if(!a)return!1;a.cancelBubble=!0;return!1},this._unbind=function(a,c,d,e){a.detachEvent?a.detachEvent("on"+c,d):a["on"+c]=!1});this.unbindAll=function(){for(var b=0;b<a.events.length;b++){var c=a.events[b];c.q?c.e.unbind(c.n,c.f):a._unbind(c.e,c.n,c.f,c.b)}};this.showRail=
-function(){0==a.page.maxh||!a.ispage&&"none"==a.win.css("display")||(a.visibility=!0,a.rail.visibility=!0,a.rail.css("display","block"));return a};this.showRailHr=function(){if(!a.railh)return a;0==a.page.maxw||!a.ispage&&"none"==a.win.css("display")||(a.railh.visibility=!0,a.railh.css("display","block"));return a};this.hideRail=function(){a.visibility=!1;a.rail.visibility=!1;a.rail.css("display","none");return a};this.hideRailHr=function(){if(!a.railh)return a;a.railh.visibility=!1;a.railh.css("display",
-"none");return a};this.show=function(){a.hidden=!1;a.railslocked=!1;return a.showRail().showRailHr()};this.hide=function(){a.hidden=!0;a.railslocked=!0;return a.hideRail().hideRailHr()};this.toggle=function(){return a.hidden?a.show():a.hide()};this.remove=function(){a.stop();a.cursortimeout&&clearTimeout(a.cursortimeout);a.doZoomOut();a.unbindAll();e.isie9&&a.win[0].detachEvent("onpropertychange",a.onAttributeChange);!1!==a.observer&&a.observer.disconnect();!1!==a.observerremover&&a.observerremover.disconnect();
-!1!==a.observerbody&&a.observerbody.disconnect();a.events=null;a.cursor&&a.cursor.remove();a.cursorh&&a.cursorh.remove();a.rail&&a.rail.remove();a.railh&&a.railh.remove();a.zoom&&a.zoom.remove();for(var b=0;b<a.saved.css.length;b++){var c=a.saved.css[b];c[0].css(c[1],"undefined"==typeof c[2]?"":c[2])}a.saved=!1;a.me.data("__nicescroll","");var d=f.nicescroll;d.each(function(b){if(this&&this.id===a.id){delete d[b];for(var c=++b;c<d.length;c++,b++)d[b]=d[c];d.length--;d.length&&delete d[d.length]}});
-for(var h in a)a[h]=null,delete a[h];a=null};this.scrollstart=function(b){this.onscrollstart=b;return a};this.scrollend=function(b){this.onscrollend=b;return a};this.scrollcancel=function(b){this.onscrollcancel=b;return a};this.zoomin=function(b){this.onzoomin=b;return a};this.zoomout=function(b){this.onzoomout=b;return a};this.isScrollable=function(a){a=a.target?a.target:a;if("OPTION"==a.nodeName)return!0;for(;a&&1==a.nodeType&&!/^BODY|HTML/.test(a.nodeName);){var c=f(a),c=c.css("overflowY")||c.css("overflowX")||
-c.css("overflow")||"";if(/scroll|auto/.test(c))return a.clientHeight!=a.scrollHeight;a=a.parentNode?a.parentNode:!1}return!1};this.getViewport=function(a){for(a=a&&a.parentNode?a.parentNode:!1;a&&1==a.nodeType&&!/^BODY|HTML/.test(a.nodeName);){var c=f(a);if(/fixed|absolute/.test(c.css("position")))return c;var d=c.css("overflowY")||c.css("overflowX")||c.css("overflow")||"";if(/scroll|auto/.test(d)&&a.clientHeight!=a.scrollHeight||0<c.getNiceScroll().length)return c;a=a.parentNode?a.parentNode:!1}return!1};
-this.triggerScrollEnd=function(){if(a.onscrollend){var b=a.getScrollLeft(),c=a.getScrollTop();a.onscrollend.call(a,{type:"scrollend",current:{x:b,y:c},end:{x:b,y:c}})}};this.onmousewheel=function(b){if(!a.wheelprevented){if(a.railslocked)return a.debounced("checkunlock",a.resize,250),!0;if(a.rail.drag)return a.cancelEvent(b);"auto"==a.opt.oneaxismousemode&&0!=b.deltaX&&(a.opt.oneaxismousemode=!1);if(a.opt.oneaxismousemode&&0==b.deltaX&&!a.rail.scrollable)return a.railh&&a.railh.scrollable?a.onmousewheelhr(b):
-!0;var c=+new Date,d=!1;a.opt.preservenativescrolling&&a.checkarea+600<c&&(a.nativescrollingarea=a.isScrollable(b),d=!0);a.checkarea=c;if(a.nativescrollingarea)return!0;if(b=p(b,!1,d))a.checkarea=0;return b}};this.onmousewheelhr=function(b){if(!a.wheelprevented){if(a.railslocked||!a.railh.scrollable)return!0;if(a.rail.drag)return a.cancelEvent(b);var c=+new Date,d=!1;a.opt.preservenativescrolling&&a.checkarea+600<c&&(a.nativescrollingarea=a.isScrollable(b),d=!0);a.checkarea=c;return a.nativescrollingarea?
-!0:a.railslocked?a.cancelEvent(b):p(b,!0,d)}};this.stop=function(){a.cancelScroll();a.scrollmon&&a.scrollmon.stop();a.cursorfreezed=!1;a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y));a.noticeCursor();return a};this.getTransitionSpeed=function(b){var c=Math.round(10*a.opt.scrollspeed);b=Math.min(c,Math.round(b/20*a.opt.scrollspeed));return 20<b?b:0};a.opt.smoothscroll?a.ishwscroll&&e.hastransition&&a.opt.usetransition&&a.opt.smoothscroll?(this.prepareTransition=function(b,c){var d=c?20<
-b?b:0:a.getTransitionSpeed(b),f=d?e.prefixstyle+"transform "+d+"ms ease-out":"";a.lasttransitionstyle&&a.lasttransitionstyle==f||(a.lasttransitionstyle=f,a.doc.css(e.transitionstyle,f));return d},this.doScrollLeft=function(b,c){var d=a.scrollrunning?a.newscrolly:a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b,c){var d=a.scrollrunning?a.newscrollx:a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){var f=a.getScrollTop(),h=a.getScrollLeft();(0>(a.newscrolly-
-f)*(c-f)||0>(a.newscrollx-h)*(b-h))&&a.cancelScroll();0==a.opt.bouncescroll&&(0>c?c=0:c>a.page.maxh&&(c=a.page.maxh),0>b?b=0:b>a.page.maxw&&(b=a.page.maxw));if(a.scrollrunning&&b==a.newscrollx&&c==a.newscrolly)return!1;a.newscrolly=c;a.newscrollx=b;a.newscrollspeed=d||!1;if(a.timer)return!1;a.timer=setTimeout(function(){var d=a.getScrollTop(),f=a.getScrollLeft(),h,k;h=b-f;k=c-d;h=Math.round(Math.sqrt(Math.pow(h,2)+Math.pow(k,2)));h=a.newscrollspeed&&1<a.newscrollspeed?a.newscrollspeed:a.getTransitionSpeed(h);
-a.newscrollspeed&&1>=a.newscrollspeed&&(h*=a.newscrollspeed);a.prepareTransition(h,!0);a.timerscroll&&a.timerscroll.tm&&clearInterval(a.timerscroll.tm);0<h&&(!a.scrollrunning&&a.onscrollstart&&a.onscrollstart.call(a,{type:"scrollstart",current:{x:f,y:d},request:{x:b,y:c},end:{x:a.newscrollx,y:a.newscrolly},speed:h}),e.transitionend?a.scrollendtrapped||(a.scrollendtrapped=!0,a.bind(a.doc,e.transitionend,a.onScrollTransitionEnd,!1)):(a.scrollendtrapped&&clearTimeout(a.scrollendtrapped),a.scrollendtrapped=
-setTimeout(a.onScrollTransitionEnd,h)),a.timerscroll={bz:new A(d,a.newscrolly,h,0,0,.58,1),bh:new A(f,a.newscrollx,h,0,0,.58,1)},a.cursorfreezed||(a.timerscroll.tm=setInterval(function(){a.showCursor(a.getScrollTop(),a.getScrollLeft())},60)));a.synched("doScroll-set",function(){a.timer=0;a.scrollendtrapped&&(a.scrollrunning=!0);a.setScrollTop(a.newscrolly);a.setScrollLeft(a.newscrollx);if(!a.scrollendtrapped)a.onScrollTransitionEnd()})},50)},this.cancelScroll=function(){if(!a.scrollendtrapped)return!0;
-var b=a.getScrollTop(),c=a.getScrollLeft();a.scrollrunning=!1;e.transitionend||clearTimeout(e.transitionend);a.scrollendtrapped=!1;a._unbind(a.doc[0],e.transitionend,a.onScrollTransitionEnd);a.prepareTransition(0);a.setScrollTop(b);a.railh&&a.setScrollLeft(c);a.timerscroll&&a.timerscroll.tm&&clearInterval(a.timerscroll.tm);a.timerscroll=!1;a.cursorfreezed=!1;a.showCursor(b,c);return a},this.onScrollTransitionEnd=function(){a.scrollendtrapped&&a._unbind(a.doc[0],e.transitionend,a.onScrollTransitionEnd);
-a.scrollendtrapped=!1;a.prepareTransition(0);a.timerscroll&&a.timerscroll.tm&&clearInterval(a.timerscroll.tm);a.timerscroll=!1;var b=a.getScrollTop(),c=a.getScrollLeft();a.setScrollTop(b);a.railh&&a.setScrollLeft(c);a.noticeCursor(!1,b,c);a.cursorfreezed=!1;0>b?b=0:b>a.page.maxh&&(b=a.page.maxh);0>c?c=0:c>a.page.maxw&&(c=a.page.maxw);if(b!=a.newscrolly||c!=a.newscrollx)return a.doScrollPos(c,b,a.opt.snapbackspeed);a.onscrollend&&a.scrollrunning&&a.triggerScrollEnd();a.scrollrunning=!1}):(this.doScrollLeft=
-function(b,c){var d=a.scrollrunning?a.newscrolly:a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b,c){var d=a.scrollrunning?a.newscrollx:a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){function e(){if(a.cancelAnimationFrame)return!0;a.scrollrunning=!0;if(n=1-n)return a.timer=s(e)||1;var b=0,c,d,g=d=a.getScrollTop();if(a.dst.ay){g=a.bzscroll?a.dst.py+a.bzscroll.getNow()*a.dst.ay:a.newscrolly;c=g-d;if(0>c&&g<a.newscrolly||0<c&&g>a.newscrolly)g=a.newscrolly;
-a.setScrollTop(g);g==a.newscrolly&&(b=1)}else b=1;d=c=a.getScrollLeft();if(a.dst.ax){d=a.bzscroll?a.dst.px+a.bzscroll.getNow()*a.dst.ax:a.newscrollx;c=d-c;if(0>c&&d<a.newscrollx||0<c&&d>a.newscrollx)d=a.newscrollx;a.setScrollLeft(d);d==a.newscrollx&&(b+=1)}else b+=1;2==b?(a.timer=0,a.cursorfreezed=!1,a.bzscroll=!1,a.scrollrunning=!1,0>g?g=0:g>a.page.maxh&&(g=a.page.maxh),0>d?d=0:d>a.page.maxw&&(d=a.page.maxw),d!=a.newscrollx||g!=a.newscrolly?a.doScrollPos(d,g):a.onscrollend&&a.triggerScrollEnd()):
-a.timer=s(e)||1}c="undefined"==typeof c||!1===c?a.getScrollTop(!0):c;if(a.timer&&a.newscrolly==c&&a.newscrollx==b)return!0;a.timer&&t(a.timer);a.timer=0;var f=a.getScrollTop(),h=a.getScrollLeft();(0>(a.newscrolly-f)*(c-f)||0>(a.newscrollx-h)*(b-h))&&a.cancelScroll();a.newscrolly=c;a.newscrollx=b;a.bouncescroll&&a.rail.visibility||(0>a.newscrolly?a.newscrolly=0:a.newscrolly>a.page.maxh&&(a.newscrolly=a.page.maxh));a.bouncescroll&&a.railh.visibility||(0>a.newscrollx?a.newscrollx=0:a.newscrollx>a.page.maxw&&
-(a.newscrollx=a.page.maxw));a.dst={};a.dst.x=b-h;a.dst.y=c-f;a.dst.px=h;a.dst.py=f;var k=Math.round(Math.sqrt(Math.pow(a.dst.x,2)+Math.pow(a.dst.y,2)));a.dst.ax=a.dst.x/k;a.dst.ay=a.dst.y/k;var l=0,m=k;0==a.dst.x?(l=f,m=c,a.dst.ay=1,a.dst.py=0):0==a.dst.y&&(l=h,m=b,a.dst.ax=1,a.dst.px=0);k=a.getTransitionSpeed(k);d&&1>=d&&(k*=d);a.bzscroll=0<k?a.bzscroll?a.bzscroll.update(m,k):new A(l,m,k,0,1,0,1):!1;if(!a.timer){(f==a.page.maxh&&c>=a.page.maxh||h==a.page.maxw&&b>=a.page.maxw)&&a.checkContentSize();
-var n=1;a.cancelAnimationFrame=!1;a.timer=1;a.onscrollstart&&!a.scrollrunning&&a.onscrollstart.call(a,{type:"scrollstart",current:{x:h,y:f},request:{x:b,y:c},end:{x:a.newscrollx,y:a.newscrolly},speed:k});e();(f==a.page.maxh&&c>=f||h==a.page.maxw&&b>=h)&&a.checkContentSize();a.noticeCursor()}},this.cancelScroll=function(){a.timer&&t(a.timer);a.timer=0;a.bzscroll=!1;a.scrollrunning=!1;return a}):(this.doScrollLeft=function(b,c){var d=a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b,
-c){var d=a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){var e=b>a.page.maxw?a.page.maxw:b;0>e&&(e=0);var f=c>a.page.maxh?a.page.maxh:c;0>f&&(f=0);a.synched("scroll",function(){a.setScrollTop(f);a.setScrollLeft(e)})},this.cancelScroll=function(){});this.doScrollBy=function(b,c){var d=0,d=c?Math.floor((a.scroll.y-b)*a.scrollratio.y):(a.timer?a.newscrolly:a.getScrollTop(!0))-b;if(a.bouncescroll){var e=Math.round(a.view.h/2);d<-e?d=-e:d>a.page.maxh+e&&(d=a.page.maxh+e)}a.cursorfreezed=
-!1;e=a.getScrollTop(!0);if(0>d&&0>=e)return a.noticeCursor();if(d>a.page.maxh&&e>=a.page.maxh)return a.checkContentSize(),a.noticeCursor();a.doScrollTop(d)};this.doScrollLeftBy=function(b,c){var d=0,d=c?Math.floor((a.scroll.x-b)*a.scrollratio.x):(a.timer?a.newscrollx:a.getScrollLeft(!0))-b;if(a.bouncescroll){var e=Math.round(a.view.w/2);d<-e?d=-e:d>a.page.maxw+e&&(d=a.page.maxw+e)}a.cursorfreezed=!1;e=a.getScrollLeft(!0);if(0>d&&0>=e||d>a.page.maxw&&e>=a.page.maxw)return a.noticeCursor();a.doScrollLeft(d)};
-this.doScrollTo=function(b,c){c&&Math.round(b*a.scrollratio.y);a.cursorfreezed=!1;a.doScrollTop(b)};this.checkContentSize=function(){var b=a.getContentSize();b.h==a.page.h&&b.w==a.page.w||a.resize(!1,b)};a.onscroll=function(b){a.rail.drag||a.cursorfreezed||a.synched("scroll",function(){a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y));a.railh&&(a.scroll.x=Math.round(a.getScrollLeft()*(1/a.scrollratio.x)));a.noticeCursor()})};a.bind(a.docscroll,"scroll",a.onscroll);this.doZoomIn=function(b){if(!a.zoomactive){a.zoomactive=
-!0;a.zoomrestore={style:{}};var c="position top left zIndex backgroundColor marginTop marginBottom marginLeft marginRight".split(" "),d=a.win[0].style,h;for(h in c){var k=c[h];a.zoomrestore.style[k]="undefined"!=typeof d[k]?d[k]:""}a.zoomrestore.style.width=a.win.css("width");a.zoomrestore.style.height=a.win.css("height");a.zoomrestore.padding={w:a.win.outerWidth()-a.win.width(),h:a.win.outerHeight()-a.win.height()};e.isios4&&(a.zoomrestore.scrollTop=f(window).scrollTop(),f(window).scrollTop(0));
-a.win.css({position:e.isios4?"absolute":"fixed",top:0,left:0,"z-index":x+100,margin:"0px"});c=a.win.css("backgroundColor");(""==c||/transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(c))&&a.win.css("backgroundColor","#fff");a.rail.css({"z-index":x+101});a.zoom.css({"z-index":x+102});a.zoom.css("backgroundPosition","0px -18px");a.resizeZoom();a.onzoomin&&a.onzoomin.call(a);return a.cancelEvent(b)}};this.doZoomOut=function(b){if(a.zoomactive)return a.zoomactive=!1,a.win.css("margin",""),a.win.css(a.zoomrestore.style),
-e.isios4&&f(window).scrollTop(a.zoomrestore.scrollTop),a.rail.css({"z-index":a.zindex}),a.zoom.css({"z-index":a.zindex}),a.zoomrestore=!1,a.zoom.css("backgroundPosition","0px 0px"),a.onResize(),a.onzoomout&&a.onzoomout.call(a),a.cancelEvent(b)};this.doZoom=function(b){return a.zoomactive?a.doZoomOut(b):a.doZoomIn(b)};this.resizeZoom=function(){if(a.zoomactive){var b=a.getScrollTop();a.win.css({width:f(window).width()-a.zoomrestore.padding.w+"px",height:f(window).height()-a.zoomrestore.padding.h+"px"});
-a.onResize();a.setScrollTop(Math.min(a.page.maxh,b))}};this.init();f.nicescroll.push(this)},L=function(f){var c=this;this.nc=f;this.steptime=this.lasttime=this.speedy=this.speedx=this.lasty=this.lastx=0;this.snapy=this.snapx=!1;this.demuly=this.demulx=0;this.lastscrolly=this.lastscrollx=-1;this.timer=this.chky=this.chkx=0;this.time=function(){return+new Date};this.reset=function(f,k){c.stop();var d=c.time();c.steptime=0;c.lasttime=d;c.speedx=0;c.speedy=0;c.lastx=f;c.lasty=k;c.lastscrollx=-1;c.lastscrolly=
--1};this.update=function(f,k){var d=c.time();c.steptime=d-c.lasttime;c.lasttime=d;var d=k-c.lasty,n=f-c.lastx,p=c.nc.getScrollTop(),a=c.nc.getScrollLeft(),p=p+d,a=a+n;c.snapx=0>a||a>c.nc.page.maxw;c.snapy=0>p||p>c.nc.page.maxh;c.speedx=n;c.speedy=d;c.lastx=f;c.lasty=k};this.stop=function(){c.nc.unsynched("domomentum2d");c.timer&&clearTimeout(c.timer);c.timer=0;c.lastscrollx=-1;c.lastscrolly=-1};this.doSnapy=function(f,k){var d=!1;0>k?(k=0,d=!0):k>c.nc.page.maxh&&(k=c.nc.page.maxh,d=!0);0>f?(f=0,d=
-!0):f>c.nc.page.maxw&&(f=c.nc.page.maxw,d=!0);d?c.nc.doScrollPos(f,k,c.nc.opt.snapbackspeed):c.nc.triggerScrollEnd()};this.doMomentum=function(f){var k=c.time(),d=f?k+f:c.lasttime;f=c.nc.getScrollLeft();var n=c.nc.getScrollTop(),p=c.nc.page.maxh,a=c.nc.page.maxw;c.speedx=0<a?Math.min(60,c.speedx):0;c.speedy=0<p?Math.min(60,c.speedy):0;d=d&&60>=k-d;if(0>n||n>p||0>f||f>a)d=!1;f=c.speedx&&d?c.speedx:!1;if(c.speedy&&d&&c.speedy||f){var s=Math.max(16,c.steptime);50<s&&(f=s/50,c.speedx*=f,c.speedy*=f,s=
-50);c.demulxy=0;c.lastscrollx=c.nc.getScrollLeft();c.chkx=c.lastscrollx;c.lastscrolly=c.nc.getScrollTop();c.chky=c.lastscrolly;var e=c.lastscrollx,r=c.lastscrolly,t=function(){var d=600<c.time()-k?.04:.02;c.speedx&&(e=Math.floor(c.lastscrollx-c.speedx*(1-c.demulxy)),c.lastscrollx=e,0>e||e>a)&&(d=.1);c.speedy&&(r=Math.floor(c.lastscrolly-c.speedy*(1-c.demulxy)),c.lastscrolly=r,0>r||r>p)&&(d=.1);c.demulxy=Math.min(1,c.demulxy+d);c.nc.synched("domomentum2d",function(){c.speedx&&(c.nc.getScrollLeft()!=
-c.chkx&&c.stop(),c.chkx=e,c.nc.setScrollLeft(e));c.speedy&&(c.nc.getScrollTop()!=c.chky&&c.stop(),c.chky=r,c.nc.setScrollTop(r));c.timer||(c.nc.hideCursor(),c.doSnapy(e,r))});1>c.demulxy?c.timer=setTimeout(t,s):(c.stop(),c.nc.hideCursor(),c.doSnapy(e,r))};t()}else c.doSnapy(c.nc.getScrollLeft(),c.nc.getScrollTop())}},w=f.fn.scrollTop;f.cssHooks.pageYOffset={get:function(k,c,h){return(c=f.data(k,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollTop():w.call(k)},set:function(k,c){var h=f.data(k,"__nicescroll")||
-!1;h&&h.ishwscroll?h.setScrollTop(parseInt(c)):w.call(k,c);return this}};f.fn.scrollTop=function(k){if("undefined"==typeof k){var c=this[0]?f.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollTop():w.call(this)}return this.each(function(){var c=f.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollTop(parseInt(k)):w.call(f(this),k)})};var B=f.fn.scrollLeft;f.cssHooks.pageXOffset={get:function(k,c,h){return(c=f.data(k,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollLeft():B.call(k)},
-set:function(k,c){var h=f.data(k,"__nicescroll")||!1;h&&h.ishwscroll?h.setScrollLeft(parseInt(c)):B.call(k,c);return this}};f.fn.scrollLeft=function(k){if("undefined"==typeof k){var c=this[0]?f.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollLeft():B.call(this)}return this.each(function(){var c=f.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollLeft(parseInt(k)):B.call(f(this),k)})};var C=function(k){var c=this;this.length=0;this.name="nicescrollarray";this.each=function(d){for(var f=
-0,h=0;f<c.length;f++)d.call(c[f],h++);return c};this.push=function(d){c[c.length]=d;c.length++};this.eq=function(d){return c[d]};if(k)for(var h=0;h<k.length;h++){var m=f.data(k[h],"__nicescroll")||!1;m&&(this[this.length]=m,this.length++)}return this};(function(f,c,h){for(var m=0;m<c.length;m++)h(f,c[m])})(C.prototype,"show hide toggle onResize resize remove stop doScrollPos".split(" "),function(f,c){f[c]=function(){var f=arguments;return this.each(function(){this[c].apply(this,f)})}});f.fn.getNiceScroll=
-function(k){return"undefined"==typeof k?new C(this):this[k]&&f.data(this[k],"__nicescroll")||!1};f.extend(f.expr[":"],{nicescroll:function(k){return f.data(k,"__nicescroll")?!0:!1}});f.fn.niceScroll=function(k,c){"undefined"!=typeof c||"object"!=typeof k||"jquery"in k||(c=k,k=!1);c=f.extend({},c);var h=new C;"undefined"==typeof c&&(c={});k&&(c.doc=f(k),c.win=f(this));var m=!("doc"in c);m||"win"in c||(c.win=f(this));this.each(function(){var d=f(this).data("__nicescroll")||!1;d||(c.doc=m?f(this):c.doc,
-d=new R(c,f(this)),f(this).data("__nicescroll",d));h.push(d)});return 1==h.length?h[0]:h};window.NiceScroll={getjQuery:function(){return f}};f.nicescroll||(f.nicescroll=new C,f.nicescroll.options=I)});