diff options
author | Robert Speicher <rspeicher@gmail.com> | 2016-01-23 17:44:40 -0800 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2016-01-23 17:45:39 -0800 |
commit | d66826630614c9b47f2062e3d2c98ad519d31ce4 (patch) | |
tree | de4243517aabc9df92bb9a28b2cee7b28e2d8d75 | |
parent | 5409fc49bd7fb1e24f048ec5b8931b216b6ceda8 (diff) | |
parent | 82a3cfc151c4c96935387be3e94f703beb449b25 (diff) | |
download | gitlab-ce-d66826630614c9b47f2062e3d2c98ad519d31ce4.tar.gz |
Merge branch 'rs-no-minified-js'
Don't vendor minified JS
Fixes #4031
See merge request !2494
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | app/assets/javascripts/application.js.coffee | 10 | ||||
-rwxr-xr-x | vendor/assets/javascripts/Chart.js | 3477 | ||||
-rw-r--r-- | vendor/assets/javascripts/chart-lib.min.js | 11 | ||||
-rw-r--r-- | vendor/assets/javascripts/fuzzaldrin-plus.js | 1161 | ||||
-rw-r--r-- | vendor/assets/javascripts/fuzzaldrin-plus.min.js | 1 | ||||
-rw-r--r-- | vendor/assets/javascripts/g.bar-min.js | 8 | ||||
-rw-r--r-- | vendor/assets/javascripts/g.bar.js | 674 | ||||
-rw-r--r-- | vendor/assets/javascripts/g.raphael-min.js | 7 | ||||
-rw-r--r-- | vendor/assets/javascripts/g.raphael.js | 861 | ||||
-rw-r--r-- | vendor/assets/javascripts/jquery.nicescroll.js | 3634 | ||||
-rw-r--r-- | vendor/assets/javascripts/jquery.nicescroll.min.js | 118 |
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)}); |