# HG changeset patch # User Harris Baptiste # Date 1467364704 -7200 # Node ID ca0bb73ac8b52989b32f76e4e93fd3c352ac9ba5 # Parent 6730ec4d7e3729386a963c98f5f2f5034ab6731f removing files diff -r 6730ec4d7e37 -r ca0bb73ac8b5 src/iconolab/static/iconolab/js/components/cutout/index.js --- a/src/iconolab/static/iconolab/js/components/cutout/index.js Fri Jul 01 11:15:37 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,523 +0,0 @@ - -var Snap = require('snapsvg'); -ShapeResizer = require("./shape-resizer"); -eventEmitter = require("event-emitter")({}); - -/* custom plugin */ -Snap.plugin(function (Snap, Element, Paper, glob) { - var elproto = Element.prototype; - - elproto.toBack = function () { - this.prependTo(this.paper); - }; - - elproto.toFront = function () { - this.appendTo(this.paper); - }; -}); - -Element.prototype.getTransformedXY = function( x,y ) { - var m = this.transform().globalMatrix; - return { x: m.x(x,y), y: m.y(x,y) }; - }; - -var paper = null; -var mainImage = null; -var pointData = []; -var viewBoxBounds = {X: 100, Y:100}; -var config = null; -var readOnly = false; -var startPoint = null; -var drawing_path = null; -var canDraw = false; -var rectZone = null; -var PATH_COLOR = "#ff00ff"; -var STROKE_COLOR = "red"; -var FILL_COLOR = "orange"; - -var SELECTED_COLOR = "#ffff00"; -var FIRST_NODE_COLOR = "#FF0000"; -var HANDLE_SIZE = 6; -var isDragged = false; -var enablePoint = true; -var pathIsClosed = false; -var ENABLE_NEW_NODE = true; -var RECT_MODE ='RECT'; -var drawingMode = RECT_MODE; //free -var FREE_MODE = 'FREE'; -var availableModes = [RECT_MODE, FREE_MODE]; -var onChangeCallback = null; - -var getId = (function () { - var cpt = 0; - var defautPrefix = "item_"; - return function (prefix) { - prefix = (typeof prefix === 'string') ? prefix : defautPrefix; - cpt = cpt + 1; - return prefix + cpt; - } - }()); - -var handleRectPath = function (path) { - if (readOnly) { - paper.path(path).attr({ stroke:'red', opacity: 0.6}); - return; - } - - var bbBox = Snap.path.getBBox(path); - rectZone = paper.rect(bbBox.x, bbBox.y, bbBox.width, bbBox.height); - rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6}); - drawing_path = rectZone; - canDraw = false; - pathIsClosed = true; - ShapeResizer.apply_resize(paper, drawing_path); -}; - - -var handleFreePath = function (path) { - - if (readOnly) { - - paper.path(path).attr({ - stroke: 'orange', - fill: 'orange', - opacity: 0.5, - }); - - return; - } - - var pathInfos = Snap.parsePathString(path); - pathInfos.map(function (pathData) { - if(pathData[0] !== 'Z') { - createPoint(paper, pathData[1], pathData[2], pointData); - } else { - pathIsClosed = true; - updatePath(paper, onClosePath); - } - }); - - /* replay the path here */ - -}; -//transform point to path -var updatePath = function (paper, updateCallback) { - var path = "M"; - - if (pointData.length <= 1) { - return; - } - - path += pointData[0].x + ',' + pointData[0].y; - - for (var i=0; i < pointData.length; i++) { - if (i == 0) continue; - - var pointInfos = pointData[i]; - lPath = "L" + pointInfos.x + "," + pointInfos.y; - path += " " + lPath; - } - - path += (pathIsClosed) ? " Z": ""; - - /* remove prev path */ - if (drawing_path) { - drawing_path.remove(); - } - - drawing_path = paper.path(path); - - drawing_path.attr({ - stroke: STROKE_COLOR, - "stroke-width": 3, - fill: "white", - opacity: 0.1 - }); - - /* bring all handler to front */ - pointData.map(function (point) { - if (point.handler) { - point.handler.toFront(); - } - }); - - if (typeof updateCallback === 'function' && pathIsClosed) { - updateCallback(); - } - - if (!updateCallback && pathIsClosed) { - applyClosedStyle(); - } -}; - -var applyClosedStyle = function () { - drawing_path.attr({ fill: FILL_COLOR, strokeWidth: 1, opacity:.6 }); -} - -var onClosePath = function () { - ENABLE_NEW_NODE = false; - applyClosedStyle(); -}; - - -var onClickOnHandler = function (point, p, e) { - //close path - if (point.isFirst && pointData.length > 2) { - pathIsClosed = true; - } -}; - -var updatePointPosition = function (newPoint, x, y) { - var index = pointData.indexOf(newPoint); - if (index !== -1) { - pointData[index].x = x; - pointData[index].y = y; - return true; - } else { - return false; - } -}; - -var clearPreviousPath = function () { - drawing_path.remove(); -}; - -var onMoveHandler = function (dx, dy, posX, posY, e) { - isDragged = true; - /* update point then update the view */ - var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]; - this.attr({ transform: transformValue}); - var boxSize = this.getBBox(); - - var wasUpdated = updatePointPosition(this.data('point'), boxSize.x + (HANDLE_SIZE / 2) , boxSize.y + (HANDLE_SIZE / 2)); - - if (wasUpdated) { - updatePath(this.paper); - } -} - -var bindHandlerEvent = function (point, p) { - point.handler.click(onClickOnHandler.bind(this, point, p)); - /* -- handler -- */ - point.handler.hover(function () { - point.handler.attr({fill: 'yellow'}); - }, function () { - var fillColor = point.isFirst ? FIRST_NODE_COLOR : ""; - point.handler.attr({fill: fillColor}); - }); - - point.handler.drag(onMoveHandler, function () { - this.data('origTransform', this.transform().local ); - }, function () { - if (!isDragged) { return true; } - isDragged = false; - enablePoint = false; - }); -} - -var createPointHandler = function (p, point) { - - var handleX = point.x - HANDLE_SIZE/2; - var handleY = point.y - HANDLE_SIZE/2; - - handler = p.rect(handleX, handleY, HANDLE_SIZE, HANDLE_SIZE); - - point.handler = handler; - point.handler.data('point', point); - if (pointData.length === 0) { - point.isFirst = true; - } - - bindHandlerEvent(point, p); - point.handler.attr({ - fill: (pointData.length === 0) ? FIRST_NODE_COLOR : "", - opacity: 0.9, - stroke: PATH_COLOR - }); - - return point; -} - -//create paper -var createPoint = function (paper, x, y, pointData) { - - var point = {x:x, y:y, id: getId()}; - - if (pathIsClosed) { - updatePath(paper, onClosePath); - return; - } - - if (!enablePoint) { - enablePoint = true; - return false; - } - - point = createPointHandler(paper, point); - pointData.push(point); - updatePath(paper); -}; - -var attachRectEvents = function (paper) { - if (readOnly) { return false; } - - var startPosition = {}; - var currentPosition = {}; - /* add resizer */ - - paper.mousedown(function (e) { - - if (drawingMode === FREE_MODE || pathIsClosed) { return; } - startPosition.x = e.offsetX; - startPosition.y = e.offsetY; - canDraw = true; - }); - - paper.mousemove(function (e) { - if (drawingMode === FREE_MODE) { return; } - if (!canDraw) { return; } - var x, y; - currentPosition.x = e.offsetX; - currentPosition.y = e.offsetY; - - if (rectZone) { - rectZone.remove(); - } - - /* bas -> droite */ - var width = Math.abs(currentPosition.x - startPosition.x); - var height = Math.abs(startPosition.y - currentPosition.y); - - if (currentPosition.y > startPosition.y && currentPosition.x > startPosition.x) { - x = startPosition.x; - y = startPosition.y; - } - - /* haut -> droite */ - if (currentPosition.y < startPosition.y && currentPosition.x > startPosition.x) { - x = currentPosition.x - width; - y = currentPosition.y; - } - - /* haut -> gauche */ - if (currentPosition.y < startPosition.y && currentPosition.x < startPosition.x) { - x = currentPosition.x; - y = currentPosition.y; - } - - /* bas -> gauche */ - if (currentPosition.y > startPosition.y && currentPosition.x < startPosition.x) { - x = currentPosition.x - y = currentPosition.y - height; - } - if(!x || !y) { return; } - - rectZone = paper.rect(x, y, width, height); - rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6}); - }); - - - paper.mouseup(function () { - if ((drawingMode === FREE_MODE) || pathIsClosed || !rectZone) { return false; } - drawing_path = rectZone; - ShapeResizer.apply_resize(paper, rectZone); - canDraw = false; - pathIsClosed = true; - }); -}; -var attachPointEvents = function (paper) { - if (readOnly) { return; } - paper.click( function(e) { - if (drawingMode === RECT_MODE) { - return true; - } - - if (!ENABLE_NEW_NODE) { return true; } - createPoint(paper, e.offsetX, e.offsetY, pointData); - }); -}; - -var API = { - - setPath: function (pathString) { - /* redraw the path */ - var pathInfos = pathString.split(';'); - if( availableModes.indexOf(pathInfos[1]) === -1) { - /* We assume then it is a free path */ - pathInfos[1] = "FREE"; - } - - this.setDrawingMode(pathInfos[1]); - var pathData = pathInfos[0]; - - if(!pathData.length) { - return; - } - /* deal with path nomalization x = ImageWith/MaxXBound*/ - var xRatio = mainImage.width() / viewBoxBounds.X; - var yRatio = mainImage.height() / viewBoxBounds.Y; - - if(isNaN(xRatio) || isNaN(yRatio)) { - new Error('Ratio should be a number.'); - } - - var transformMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0); - path = Snap.path.map(pathData, transformMatrix).toString(); - - /* always close path */ - if (path.search(/[z|Z]/gi) === -1 ) { - path += "Z"; - } - if (pathInfos.length >= 2) { - if (pathInfos[1] === RECT_MODE) { - handleRectPath(path); - } - - if (pathInfos[1] === FREE_MODE) { - handleFreePath(path); - } - } - }, - - setDrawingMode: function (mode) { - - if (availableModes.indexOf(mode) !== -1) { - drawingMode = mode; - } - if (typeof onChangeCallback === "function") { - onChangeCallback(drawingMode); - } - - this.clear(); - }, - - clear: function () { - /* clear previous path, point, handler */ - pointData.map(function (point) { - if (point.handler) { - point.handler.remove(); - } - }); - - /*clear path is exists*/ - if (drawing_path) { - drawing_path.remove(); - } - eventEmitter.emit("cutout:clear"); - pointData = []; - startPoint = null; - drawing_path = null; - isDragged = false; - enablePoint = true; - pathIsClosed = false; - ENABLE_NEW_NODE = true; - }, - - getPath: function () { - /* retourne le chemin */ - /* send path and BBox | implement edit and load path */ - var path = ""; - if (drawing_path) { - if (drawingMode === RECT_MODE) { - var bBox = drawing_path.getBBox(); - var transform = drawing_path.transform(); - - if (!transform.global.length) { - var shapePath = drawing_path.getBBox().path; - } - - else { - - var shapeX = drawing_path.node.getAttribute('x'); - var shapeY = drawing_path.node.getAttribute('y'); - - var transformMatrix = transform.globalMatrix; - var fakeShape = paper.rect(transformMatrix.x(shapeX, shapeY),transformMatrix.y(shapeX, shapeY), bBox.width, bBox.height); - shapePath = fakeShape.getBBox().path; - fakeShape.remove(); - } - - path = Snap.path.toAbsolute(shapePath).toString(); - - } - else { - path = drawing_path.attr('d'); - } - } - - var xRatio = viewBoxBounds.X / mainImage.width(); - var yRatio = viewBoxBounds.Y / mainImage.height(); - if(isNaN(xRatio) || isNaN(yRatio)) { - new Error('ratio should be a number.'); - } - - if (!path.length) { - path = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE"; - return path; - } - - var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0); - path = Snap.path.map(path, normalizeMatrix).toString(); - - /* save the type */ - var type = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE"; - if (path.search(/[z|Z]/gi) === -1) { - path += " Z"; - } - - path += type; - - return path; - } -}; - -/* change to a component */ -module.exports = { - - init: function(config) { - - mainImage = jQuery(config.wrapperId).find('img').eq(0); - var cutCanvas = jQuery(config.wrapperId).find('.cut-canvas').eq(0); - var path = jQuery(config.wrapperId).find('.image-path').eq(0); - - if (typeof config.onDrawingModeChange === 'function') { - onChangeCallback = config.onDrawingModeChange; - } - - if (!cutCanvas.length) { - var cutCanvas = jQuery('').addClass('cut-canvas'); - jQuery(config.wrapperId).append(cutCanvas); - } - - if (!mainImage) { - new Error(config.wrapperId + "Can't be found ..."); - } - - cutCanvas.css({ - position: 'absolute', - top: '0px', - left: '15px', - marginLeft: 'auto', - marginRight: 'auto', - width: mainImage.width(), - height: mainImage.height(), - viewBox: '0 0 100 100' - }); - - if (typeof config.readOnly === 'boolean' && config.readOnly === true) { - readOnly = true; - } - - paper = new Snap(cutCanvas.get(0)); - - if (path.length) { - jQuery(cutCanvas).append(path); - API.setPath(path.attr("d")); - } - - attachPointEvents(paper); - attachRectEvents(paper); - - return API; - }, -}; \ No newline at end of file diff -r 6730ec4d7e37 -r ca0bb73ac8b5 src/iconolab/static/iconolab/js/components/cutout/shape-resizer.js --- a/src/iconolab/static/iconolab/js/components/cutout/shape-resizer.js Fri Jul 01 11:15:37 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* Enabling us to resize a shape width a handler - #http://stackoverflow.com/questions/32390028/how-to-drag-and-resize-svg-rectangle-using-cursor-types -*/ -eventEmitter = require("event-emitter")({}); - -var ShapeResizer = function (paper, shape) { - this.paper = paper; - this.shape = shape; - this.handlers = []; - this.isResizing = false; - this.currentPosition = {}; - this.HANDLER_SIZE = 8; - this.SHAPE_MIN_SIZE = 20; - this.states = {}; - this.noop = function (){} - this.init(); -} - -var api = ShapeResizer.prototype = { - - init: function () { - this.showHandlers(); - }, - - showHandlers: function () { - /* show handler here */ - var bbox = this.shape.getBBox(); - var handleX = bbox.x - this.HANDLER_SIZE/2; - var handleY = bbox.y - this.HANDLER_SIZE/2; - handler = this.paper.rect(handleX, handleY, this.HANDLER_SIZE, this.HANDLER_SIZE).attr({fill: 'red'}); - var handlerInfos = {position: "t_r", handler: handler}; - this.handlers.push(handlerInfos); - this.shapesGroup = this.paper.g(this.shape, handler); - this.attachEvents(); - }, - - /*one handlers */ - updateShapePositions: function (handlerData, dx, dy) { - //start - var handlerBBox = handlerData.handler.getBBox(); - var shapeBBox = this.shape.data("origBbox"); - var newX = handlerBBox.x + this.HANDLER_SIZE / 2; - var newY = handlerBBox.y + this.HANDLER_SIZE / 2; - - /*to the right => reduce the size */ - var newWidth = (dx > 0) ? shapeBBox.width - dx : shapeBBox.width + Math.abs(dx); - var newHeight = (dy > 0) ? shapeBBox.height - dy : shapeBBox.height + Math.abs(dy); - var transformValue = this.shape.data('origTransform') + (this.shape.data('origTransform') ? "T" : "t") + [dx, dy]; - this.shape.attr({'transform': transformValue, width: newWidth, height: newHeight}); - }, - - dragEvents: { - onStart: function (handlerData, dx, dy, e) { - this.startPosition = {x: e.clientX, y: e.clientY}; - this.isResizing = true; - this.currentPosition = {}; - handlerData.handler.data("origTransform", handlerData.handler.transform().local); - this.shape.data("origBbox", this.shape.getBBox()); - this.shape.data("origTransform", this.shape.transform().local); - }, - - onMove: function (handlerData, dx, dy, x, y, e) { - var transformValue = handlerData.handler.data('origTransform') + (handlerData.handler.data('origTransform') ? "T" : "t") + [dx, dy]; - this.currentPosition.x = e.clientX; - this.currentPosition.y = e.clientY; - /* deal with boundaries */ - if (! this.checkBondaries(dx, dy)) { return; } - handlerData.handler.attr({ transform: transformValue}); - this.updateShapePositions(handlerData, dx, dy); - }, - - onStop: function () { - this.isResizing = false; - this.startPosition = {}; - this.currentPosition = {}; - } - }, - - checkBondaries: function (dx, dy) { - var result = true; - - if (this.shape.data("origBbox").width - dx <= this.SHAPE_MIN_SIZE) { - result = false; - } - - if (this.shape.data("origBbox").height - dy <= this.SHAPE_MIN_SIZE) { - result = false; - } - - return result; - }, - - destroy: function () { - this.handlers.map(function (handlerData) { - handlerData.handler.remove(); - }); - delete this; - }, - - attachEvents: function () { - var self = this; - this.handlers.map(function (handlerData) { - handlerData.handler.drag( - self.dragEvents.onMove.bind(self, handlerData), - self.dragEvents.onStart.bind(self, handlerData), - self.dragEvents.onStop.bind(self, handlerData)); - }); - - eventEmitter.on("cutout:clear", function () { - self.destroy(); - }); - - this.shapesGroup.drag(function (dx, dy) { - if (self.isResizing) { return; } - var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]; - this.transform(transformValue); - }, function () { - this.data('origTransform', this.transform().local); - }, this.noop); - }, -} - -module.exports = { - - apply_resize : function (paper, rect) { - new ShapeResizer(paper, rect); - } -} \ No newline at end of file diff -r 6730ec4d7e37 -r ca0bb73ac8b5 src/iconolab/static/iconolab/js/dist/bundle.js --- a/src/iconolab/static/iconolab/js/dist/bundle.js Fri Jul 01 11:15:37 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29277 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - var cutout = __webpack_require__(1); - - /* expose jQuery */ - var test = __webpack_require__(19); - - /* expose Vue */ - __webpack_require__(21); - - var api = { - initCutoutComponent: function (config) { - return cutout.init(config); - } - }; - - module.exports = api; - iconolab = api; - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - - var Snap = __webpack_require__(2); - ShapeResizer = __webpack_require__(3); - eventEmitter = __webpack_require__(4)({}); - - /* custom plugin */ - Snap.plugin(function (Snap, Element, Paper, glob) { - var elproto = Element.prototype; - - elproto.toBack = function () { - this.prependTo(this.paper); - }; - - elproto.toFront = function () { - this.appendTo(this.paper); - }; - }); - - Element.prototype.getTransformedXY = function( x,y ) { - var m = this.transform().globalMatrix; - return { x: m.x(x,y), y: m.y(x,y) }; - }; - - var paper = null; - var mainImage = null; - var pointData = []; - var viewBoxBounds = {X: 100, Y:100}; - var config = null; - var readOnly = false; - var startPoint = null; - var drawing_path = null; - var canDraw = false; - var rectZone = null; - var PATH_COLOR = "#ff00ff"; - var STROKE_COLOR = "red"; - var FILL_COLOR = "orange"; - - var SELECTED_COLOR = "#ffff00"; - var FIRST_NODE_COLOR = "#FF0000"; - var HANDLE_SIZE = 6; - var isDragged = false; - var enablePoint = true; - var pathIsClosed = false; - var ENABLE_NEW_NODE = true; - var RECT_MODE ='RECT'; - var drawingMode = RECT_MODE; //free - var FREE_MODE = 'FREE'; - var availableModes = [RECT_MODE, FREE_MODE]; - var onChangeCallback = null; - - var getId = (function () { - var cpt = 0; - var defautPrefix = "item_"; - return function (prefix) { - prefix = (typeof prefix === 'string') ? prefix : defautPrefix; - cpt = cpt + 1; - return prefix + cpt; - } - }()); - - var handleRectPath = function (path) { - if (readOnly) { - paper.path(path).attr({ stroke:'red', opacity: 0.6}); - return; - } - - var bbBox = Snap.path.getBBox(path); - rectZone = paper.rect(bbBox.x, bbBox.y, bbBox.width, bbBox.height); - rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6}); - drawing_path = rectZone; - canDraw = false; - pathIsClosed = true; - ShapeResizer.apply_resize(paper, drawing_path); - }; - - - var handleFreePath = function (path) { - - if (readOnly) { - - paper.path(path).attr({ - stroke: 'orange', - fill: 'orange', - opacity: 0.5, - }); - - return; - } - - var pathInfos = Snap.parsePathString(path); - pathInfos.map(function (pathData) { - if(pathData[0] !== 'Z') { - createPoint(paper, pathData[1], pathData[2], pointData); - } else { - pathIsClosed = true; - updatePath(paper, onClosePath); - } - }); - - /* replay the path here */ - - }; - //transform point to path - var updatePath = function (paper, updateCallback) { - var path = "M"; - - if (pointData.length <= 1) { - return; - } - - path += pointData[0].x + ',' + pointData[0].y; - - for (var i=0; i < pointData.length; i++) { - if (i == 0) continue; - - var pointInfos = pointData[i]; - lPath = "L" + pointInfos.x + "," + pointInfos.y; - path += " " + lPath; - } - - path += (pathIsClosed) ? " Z": ""; - - /* remove prev path */ - if (drawing_path) { - drawing_path.remove(); - } - - drawing_path = paper.path(path); - - drawing_path.attr({ - stroke: STROKE_COLOR, - "stroke-width": 3, - fill: "white", - opacity: 0.1 - }); - - /* bring all handler to front */ - pointData.map(function (point) { - if (point.handler) { - point.handler.toFront(); - } - }); - - if (typeof updateCallback === 'function' && pathIsClosed) { - updateCallback(); - } - - if (!updateCallback && pathIsClosed) { - applyClosedStyle(); - } - }; - - var applyClosedStyle = function () { - drawing_path.attr({ fill: FILL_COLOR, strokeWidth: 1, opacity:.6 }); - } - - var onClosePath = function () { - ENABLE_NEW_NODE = false; - applyClosedStyle(); - }; - - - var onClickOnHandler = function (point, p, e) { - //close path - if (point.isFirst && pointData.length > 2) { - pathIsClosed = true; - } - }; - - var updatePointPosition = function (newPoint, x, y) { - var index = pointData.indexOf(newPoint); - if (index !== -1) { - pointData[index].x = x; - pointData[index].y = y; - return true; - } else { - return false; - } - }; - - var clearPreviousPath = function () { - drawing_path.remove(); - }; - - var onMoveHandler = function (dx, dy, posX, posY, e) { - isDragged = true; - /* update point then update the view */ - var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]; - this.attr({ transform: transformValue}); - var boxSize = this.getBBox(); - - var wasUpdated = updatePointPosition(this.data('point'), boxSize.x + (HANDLE_SIZE / 2) , boxSize.y + (HANDLE_SIZE / 2)); - - if (wasUpdated) { - updatePath(this.paper); - } - } - - var bindHandlerEvent = function (point, p) { - point.handler.click(onClickOnHandler.bind(this, point, p)); - /* -- handler -- */ - point.handler.hover(function () { - point.handler.attr({fill: 'yellow'}); - }, function () { - var fillColor = point.isFirst ? FIRST_NODE_COLOR : ""; - point.handler.attr({fill: fillColor}); - }); - - point.handler.drag(onMoveHandler, function () { - this.data('origTransform', this.transform().local ); - }, function () { - if (!isDragged) { return true; } - isDragged = false; - enablePoint = false; - }); - } - - var createPointHandler = function (p, point) { - - var handleX = point.x - HANDLE_SIZE/2; - var handleY = point.y - HANDLE_SIZE/2; - - handler = p.rect(handleX, handleY, HANDLE_SIZE, HANDLE_SIZE); - - point.handler = handler; - point.handler.data('point', point); - if (pointData.length === 0) { - point.isFirst = true; - } - - bindHandlerEvent(point, p); - point.handler.attr({ - fill: (pointData.length === 0) ? FIRST_NODE_COLOR : "", - opacity: 0.9, - stroke: PATH_COLOR - }); - - return point; - } - - //create paper - var createPoint = function (paper, x, y, pointData) { - - var point = {x:x, y:y, id: getId()}; - - if (pathIsClosed) { - updatePath(paper, onClosePath); - return; - } - - if (!enablePoint) { - enablePoint = true; - return false; - } - - point = createPointHandler(paper, point); - pointData.push(point); - updatePath(paper); - }; - - var attachRectEvents = function (paper) { - if (readOnly) { return false; } - - var startPosition = {}; - var currentPosition = {}; - /* add resizer */ - - paper.mousedown(function (e) { - - if (drawingMode === FREE_MODE || pathIsClosed) { return; } - startPosition.x = e.offsetX; - startPosition.y = e.offsetY; - canDraw = true; - }); - - paper.mousemove(function (e) { - if (drawingMode === FREE_MODE) { return; } - if (!canDraw) { return; } - var x, y; - currentPosition.x = e.offsetX; - currentPosition.y = e.offsetY; - - if (rectZone) { - rectZone.remove(); - } - - /* bas -> droite */ - var width = Math.abs(currentPosition.x - startPosition.x); - var height = Math.abs(startPosition.y - currentPosition.y); - - if (currentPosition.y > startPosition.y && currentPosition.x > startPosition.x) { - x = startPosition.x; - y = startPosition.y; - } - - /* haut -> droite */ - if (currentPosition.y < startPosition.y && currentPosition.x > startPosition.x) { - x = currentPosition.x - width; - y = currentPosition.y; - } - - /* haut -> gauche */ - if (currentPosition.y < startPosition.y && currentPosition.x < startPosition.x) { - x = currentPosition.x; - y = currentPosition.y; - } - - /* bas -> gauche */ - if (currentPosition.y > startPosition.y && currentPosition.x < startPosition.x) { - x = currentPosition.x - y = currentPosition.y - height; - } - if(!x || !y) { return; } - - rectZone = paper.rect(x, y, width, height); - rectZone.attr({fill: FILL_COLOR, stroke: STROKE_COLOR, opacity: 0.6}); - }); - - - paper.mouseup(function () { - if ((drawingMode === FREE_MODE) || pathIsClosed || !rectZone) { return false; } - drawing_path = rectZone; - ShapeResizer.apply_resize(paper, rectZone); - canDraw = false; - pathIsClosed = true; - }); - }; - var attachPointEvents = function (paper) { - if (readOnly) { return; } - paper.click( function(e) { - if (drawingMode === RECT_MODE) { - return true; - } - - if (!ENABLE_NEW_NODE) { return true; } - createPoint(paper, e.offsetX, e.offsetY, pointData); - }); - }; - - var API = { - - setPath: function (pathString) { - /* redraw the path */ - var pathInfos = pathString.split(';'); - if( availableModes.indexOf(pathInfos[1]) === -1) { - /* We assume then it is a free path */ - pathInfos[1] = "FREE"; - } - - this.setDrawingMode(pathInfos[1]); - var pathData = pathInfos[0]; - - if(!pathData.length) { - return; - } - /* deal with path nomalization x = ImageWith/MaxXBound*/ - var xRatio = mainImage.width() / viewBoxBounds.X; - var yRatio = mainImage.height() / viewBoxBounds.Y; - - if(isNaN(xRatio) || isNaN(yRatio)) { - new Error('Ratio should be a number.'); - } - - var transformMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0); - path = Snap.path.map(pathData, transformMatrix).toString(); - - /* always close path */ - if (path.search(/[z|Z]/gi) === -1 ) { - path += "Z"; - } - if (pathInfos.length >= 2) { - if (pathInfos[1] === RECT_MODE) { - handleRectPath(path); - } - - if (pathInfos[1] === FREE_MODE) { - handleFreePath(path); - } - } - }, - - setDrawingMode: function (mode) { - - if (availableModes.indexOf(mode) !== -1) { - drawingMode = mode; - } - if (typeof onChangeCallback === "function") { - onChangeCallback(drawingMode); - } - - this.clear(); - }, - - clear: function () { - /* clear previous path, point, handler */ - pointData.map(function (point) { - if (point.handler) { - point.handler.remove(); - } - }); - - /*clear path is exists*/ - if (drawing_path) { - drawing_path.remove(); - } - eventEmitter.emit("cutout:clear"); - pointData = []; - startPoint = null; - drawing_path = null; - isDragged = false; - enablePoint = true; - pathIsClosed = false; - ENABLE_NEW_NODE = true; - }, - - getPath: function () { - /* retourne le chemin */ - /* send path and BBox | implement edit and load path */ - var path = ""; - if (drawing_path) { - if (drawingMode === RECT_MODE) { - var bBox = drawing_path.getBBox(); - var transform = drawing_path.transform(); - - if (!transform.global.length) { - var shapePath = drawing_path.getBBox().path; - } - - else { - - var shapeX = drawing_path.node.getAttribute('x'); - var shapeY = drawing_path.node.getAttribute('y'); - - var transformMatrix = transform.globalMatrix; - var fakeShape = paper.rect(transformMatrix.x(shapeX, shapeY),transformMatrix.y(shapeX, shapeY), bBox.width, bBox.height); - shapePath = fakeShape.getBBox().path; - fakeShape.remove(); - } - - path = Snap.path.toAbsolute(shapePath).toString(); - - } - else { - path = drawing_path.attr('d'); - } - } - - var xRatio = viewBoxBounds.X / mainImage.width(); - var yRatio = viewBoxBounds.Y / mainImage.height(); - if(isNaN(xRatio) || isNaN(yRatio)) { - new Error('ratio should be a number.'); - } - - if (!path.length) { - path = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE"; - return path; - } - - var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0); - path = Snap.path.map(path, normalizeMatrix).toString(); - - /* save the type */ - var type = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE"; - if (path.search(/[z|Z]/gi) === -1) { - path += " Z"; - } - - path += type; - - return path; - } - }; - - /* change to a component */ - module.exports = { - - init: function(config) { - - mainImage = jQuery(config.wrapperId).find('img').eq(0); - var cutCanvas = jQuery(config.wrapperId).find('.cut-canvas').eq(0); - var path = jQuery(config.wrapperId).find('.image-path').eq(0); - - if (typeof config.onDrawingModeChange === 'function') { - onChangeCallback = config.onDrawingModeChange; - } - - if (!cutCanvas.length) { - var cutCanvas = jQuery('').addClass('cut-canvas'); - jQuery(config.wrapperId).append(cutCanvas); - } - - if (!mainImage) { - new Error(config.wrapperId + "Can't be found ..."); - } - - cutCanvas.css({ - position: 'absolute', - top: '0px', - left: '15px', - marginLeft: 'auto', - marginRight: 'auto', - width: mainImage.width(), - height: mainImage.height(), - viewBox: '0 0 100 100' - }); - - if (typeof config.readOnly === 'boolean' && config.readOnly === true) { - readOnly = true; - } - - paper = new Snap(cutCanvas.get(0)); - - if (path.length) { - jQuery(cutCanvas).append(path); - API.setPath(path.attr("d")); - } - - attachPointEvents(paper); - attachRectEvents(paper); - - return API; - }, - }; - -/***/ }, -/* 2 */ -/***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_0__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/ - (function() { - var fix = module.exports=0; - - // Snap.svg 0.4.0 - // - // Copyright (c) 2013 – 2015 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - // - // build: 2015-04-07 - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - // ┌────────────────────────────────────────────────────────────┐ \\ - // │ Eve 0.4.2 - JavaScript Events Library │ \\ - // ├────────────────────────────────────────────────────────────┤ \\ - // │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\ - // └────────────────────────────────────────────────────────────┘ \\ - - (function (glob) { - var version = "0.4.2", - has = "hasOwnProperty", - separator = /[\.\/]/, - comaseparator = /\s*,\s*/, - wildcard = "*", - fun = function () {}, - numsort = function (a, b) { - return a - b; - }, - current_event, - stop, - events = {n: {}}, - firstDefined = function () { - for (var i = 0, ii = this.length; i < ii; i++) { - if (typeof this[i] != "undefined") { - return this[i]; - } - } - }, - lastDefined = function () { - var i = this.length; - while (--i) { - if (typeof this[i] != "undefined") { - return this[i]; - } - } - }, - /*\ - * eve - [ method ] - - * Fires event with given `name`, given scope and other parameters. - - > Arguments - - - name (string) name of the *event*, dot (`.`) or slash (`/`) separated - - scope (object) context for the event handlers - - varargs (...) the rest of arguments will be sent to event handlers - - = (object) array of returned values from the listeners. Array has two methods `.firstDefined()` and `.lastDefined()` to get first or last not `undefined` value. - \*/ - eve = function (name, scope) { - name = String(name); - var e = events, - oldstop = stop, - args = Array.prototype.slice.call(arguments, 2), - listeners = eve.listeners(name), - z = 0, - f = false, - l, - indexed = [], - queue = {}, - out = [], - ce = current_event, - errors = []; - out.firstDefined = firstDefined; - out.lastDefined = lastDefined; - current_event = name; - stop = 0; - for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) { - indexed.push(listeners[i].zIndex); - if (listeners[i].zIndex < 0) { - queue[listeners[i].zIndex] = listeners[i]; - } - } - indexed.sort(numsort); - while (indexed[z] < 0) { - l = queue[indexed[z++]]; - out.push(l.apply(scope, args)); - if (stop) { - stop = oldstop; - return out; - } - } - for (i = 0; i < ii; i++) { - l = listeners[i]; - if ("zIndex" in l) { - if (l.zIndex == indexed[z]) { - out.push(l.apply(scope, args)); - if (stop) { - break; - } - do { - z++; - l = queue[indexed[z]]; - l && out.push(l.apply(scope, args)); - if (stop) { - break; - } - } while (l) - } else { - queue[l.zIndex] = l; - } - } else { - out.push(l.apply(scope, args)); - if (stop) { - break; - } - } - } - stop = oldstop; - current_event = ce; - return out; - }; - // Undocumented. Debug only. - eve._events = events; - /*\ - * eve.listeners - [ method ] - - * Internal method which gives you array of all event handlers that will be triggered by the given `name`. - - > Arguments - - - name (string) name of the event, dot (`.`) or slash (`/`) separated - - = (array) array of event handlers - \*/ - eve.listeners = function (name) { - var names = name.split(separator), - e = events, - item, - items, - k, - i, - ii, - j, - jj, - nes, - es = [e], - out = []; - for (i = 0, ii = names.length; i < ii; i++) { - nes = []; - for (j = 0, jj = es.length; j < jj; j++) { - e = es[j].n; - items = [e[names[i]], e[wildcard]]; - k = 2; - while (k--) { - item = items[k]; - if (item) { - nes.push(item); - out = out.concat(item.f || []); - } - } - } - es = nes; - } - return out; - }; - - /*\ - * eve.on - [ method ] - ** - * Binds given event handler with a given name. You can use wildcards “`*`” for the names: - | eve.on("*.under.*", f); - | eve("mouse.under.floor"); // triggers f - * Use @eve to trigger the listener. - ** - > Arguments - ** - - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - - f (function) event handler function - ** - = (function) returned function accepts a single numeric parameter that represents z-index of the handler. It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment. - > Example: - | eve.on("mouse", eatIt)(2); - | eve.on("mouse", scream); - | eve.on("mouse", catchIt)(1); - * This will ensure that `catchIt` function will be called before `eatIt`. - * - * If you want to put your handler before non-indexed handlers, specify a negative value. - * Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in case”. - \*/ - eve.on = function (name, f) { - name = String(name); - if (typeof f != "function") { - return function () {}; - } - var names = name.split(comaseparator); - for (var i = 0, ii = names.length; i < ii; i++) { - (function (name) { - var names = name.split(separator), - e = events, - exist; - for (var i = 0, ii = names.length; i < ii; i++) { - e = e.n; - e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}}); - } - e.f = e.f || []; - for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { - exist = true; - break; - } - !exist && e.f.push(f); - }(names[i])); - } - return function (zIndex) { - if (+zIndex == +zIndex) { - f.zIndex = +zIndex; - } - }; - }; - /*\ - * eve.f - [ method ] - ** - * Returns function that will fire given event with optional arguments. - * Arguments that will be passed to the result function will be also - * concated to the list of final arguments. - | el.onclick = eve.f("click", 1, 2); - | eve.on("click", function (a, b, c) { - | console.log(a, b, c); // 1, 2, [event object] - | }); - > Arguments - - event (string) event name - - varargs (…) and any other arguments - = (function) possible event handler function - \*/ - eve.f = function (event) { - var attrs = [].slice.call(arguments, 1); - return function () { - eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0))); - }; - }; - /*\ - * eve.stop - [ method ] - ** - * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing. - \*/ - eve.stop = function () { - stop = 1; - }; - /*\ - * eve.nt - [ method ] - ** - * Could be used inside event handler to figure out actual name of the event. - ** - > Arguments - ** - - subname (string) #optional subname of the event - ** - = (string) name of the event, if `subname` is not specified - * or - = (boolean) `true`, if current event’s name contains `subname` - \*/ - eve.nt = function (subname) { - if (subname) { - return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event); - } - return current_event; - }; - /*\ - * eve.nts - [ method ] - ** - * Could be used inside event handler to figure out actual name of the event. - ** - ** - = (array) names of the event - \*/ - eve.nts = function () { - return current_event.split(separator); - }; - /*\ - * eve.off - [ method ] - ** - * Removes given function from the list of event listeners assigned to given name. - * If no arguments specified all the events will be cleared. - ** - > Arguments - ** - - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - - f (function) event handler function - \*/ - /*\ - * eve.unbind - [ method ] - ** - * See @eve.off - \*/ - eve.off = eve.unbind = function (name, f) { - if (!name) { - eve._events = events = {n: {}}; - return; - } - var names = name.split(comaseparator); - if (names.length > 1) { - for (var i = 0, ii = names.length; i < ii; i++) { - eve.off(names[i], f); - } - return; - } - names = name.split(separator); - var e, - key, - splice, - i, ii, j, jj, - cur = [events]; - for (i = 0, ii = names.length; i < ii; i++) { - for (j = 0; j < cur.length; j += splice.length - 2) { - splice = [j, 1]; - e = cur[j].n; - if (names[i] != wildcard) { - if (e[names[i]]) { - splice.push(e[names[i]]); - } - } else { - for (key in e) if (e[has](key)) { - splice.push(e[key]); - } - } - cur.splice.apply(cur, splice); - } - } - for (i = 0, ii = cur.length; i < ii; i++) { - e = cur[i]; - while (e.n) { - if (f) { - if (e.f) { - for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) { - e.f.splice(j, 1); - break; - } - !e.f.length && delete e.f; - } - for (key in e.n) if (e.n[has](key) && e.n[key].f) { - var funcs = e.n[key].f; - for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) { - funcs.splice(j, 1); - break; - } - !funcs.length && delete e.n[key].f; - } - } else { - delete e.f; - for (key in e.n) if (e.n[has](key) && e.n[key].f) { - delete e.n[key].f; - } - } - e = e.n; - } - } - }; - /*\ - * eve.once - [ method ] - ** - * Binds given event handler with a given name to only run once then unbind itself. - | eve.once("login", f); - | eve("login"); // triggers f - | eve("login"); // no listeners - * Use @eve to trigger the listener. - ** - > Arguments - ** - - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - - f (function) event handler function - ** - = (function) same return function as @eve.on - \*/ - eve.once = function (name, f) { - var f2 = function () { - eve.unbind(name, f2); - return f.apply(this, arguments); - }; - return eve.on(name, f2); - }; - /*\ - * eve.version - [ property (string) ] - ** - * Current version of the library. - \*/ - eve.version = version; - eve.toString = function () { - return "You are running Eve " + version; - }; - (typeof module != "undefined" && module.exports) ? (module.exports = eve) : ( true ? (!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_LOCAL_MODULE_0__ = (function() { return eve; }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)))) : (glob.eve = eve)); - })(this); - - (function (glob, factory) { - // AMD support - if (true) { - // Define as an anonymous module - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__WEBPACK_LOCAL_MODULE_0__], __WEBPACK_AMD_DEFINE_RESULT__ = function (eve) { - return factory(glob, eve); - }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (typeof exports != 'undefined') { - // Next for Node.js or CommonJS - var eve = require('eve'); - module.exports = factory(glob, eve); - } else { - // Browser globals (glob is window) - // Snap adds itself to window - factory(glob, glob.eve); - } - }(window || this, function (window, eve) { - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - var mina = (function (eve) { - var animations = {}, - requestAnimFrame = window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function (callback) { - setTimeout(callback, 16); - }, - isArray = Array.isArray || function (a) { - return a instanceof Array || - Object.prototype.toString.call(a) == "[object Array]"; - }, - idgen = 0, - idprefix = "M" + (+new Date).toString(36), - ID = function () { - return idprefix + (idgen++).toString(36); - }, - diff = function (a, b, A, B) { - if (isArray(a)) { - res = []; - for (var i = 0, ii = a.length; i < ii; i++) { - res[i] = diff(a[i], b, A[i], B); - } - return res; - } - var dif = (A - a) / (B - b); - return function (bb) { - return a + dif * (bb - b); - }; - }, - timer = Date.now || function () { - return +new Date; - }, - sta = function (val) { - var a = this; - if (val == null) { - return a.s; - } - var ds = a.s - val; - a.b += a.dur * ds; - a.B += a.dur * ds; - a.s = val; - }, - speed = function (val) { - var a = this; - if (val == null) { - return a.spd; - } - a.spd = val; - }, - duration = function (val) { - var a = this; - if (val == null) { - return a.dur; - } - a.s = a.s * val / a.dur; - a.dur = val; - }, - stopit = function () { - var a = this; - delete animations[a.id]; - a.update(); - eve("mina.stop." + a.id, a); - }, - pause = function () { - var a = this; - if (a.pdif) { - return; - } - delete animations[a.id]; - a.update(); - a.pdif = a.get() - a.b; - }, - resume = function () { - var a = this; - if (!a.pdif) { - return; - } - a.b = a.get() - a.pdif; - delete a.pdif; - animations[a.id] = a; - }, - update = function () { - var a = this, - res; - if (isArray(a.start)) { - res = []; - for (var j = 0, jj = a.start.length; j < jj; j++) { - res[j] = +a.start[j] + - (a.end[j] - a.start[j]) * a.easing(a.s); - } - } else { - res = +a.start + (a.end - a.start) * a.easing(a.s); - } - a.set(res); - }, - frame = function () { - var len = 0; - for (var i in animations) if (animations.hasOwnProperty(i)) { - var a = animations[i], - b = a.get(), - res; - len++; - a.s = (b - a.b) / (a.dur / a.spd); - if (a.s >= 1) { - delete animations[i]; - a.s = 1; - len--; - (function (a) { - setTimeout(function () { - eve("mina.finish." + a.id, a); - }); - }(a)); - } - a.update(); - } - len && requestAnimFrame(frame); - }, - /*\ - * mina - [ method ] - ** - * Generic animation of numbers - ** - - a (number) start _slave_ number - - A (number) end _slave_ number - - b (number) start _master_ number (start time in general case) - - B (number) end _master_ number (end time in gereal case) - - get (function) getter of _master_ number (see @mina.time) - - set (function) setter of _slave_ number - - easing (function) #optional easing function, default is @mina.linear - = (object) animation descriptor - o { - o id (string) animation id, - o start (number) start _slave_ number, - o end (number) end _slave_ number, - o b (number) start _master_ number, - o s (number) animation status (0..1), - o dur (number) animation duration, - o spd (number) animation speed, - o get (function) getter of _master_ number (see @mina.time), - o set (function) setter of _slave_ number, - o easing (function) easing function, default is @mina.linear, - o status (function) status getter/setter, - o speed (function) speed getter/setter, - o duration (function) duration getter/setter, - o stop (function) animation stopper - o pause (function) pauses the animation - o resume (function) resumes the animation - o update (function) calles setter with the right value of the animation - o } - \*/ - mina = function (a, A, b, B, get, set, easing) { - var anim = { - id: ID(), - start: a, - end: A, - b: b, - s: 0, - dur: B - b, - spd: 1, - get: get, - set: set, - easing: easing || mina.linear, - status: sta, - speed: speed, - duration: duration, - stop: stopit, - pause: pause, - resume: resume, - update: update - }; - animations[anim.id] = anim; - var len = 0, i; - for (i in animations) if (animations.hasOwnProperty(i)) { - len++; - if (len == 2) { - break; - } - } - len == 1 && requestAnimFrame(frame); - return anim; - }; - /*\ - * mina.time - [ method ] - ** - * Returns the current time. Equivalent to: - | function () { - | return (new Date).getTime(); - | } - \*/ - mina.time = timer; - /*\ - * mina.getById - [ method ] - ** - * Returns an animation by its id - - id (string) animation's id - = (object) See @mina - \*/ - mina.getById = function (id) { - return animations[id] || null; - }; - - /*\ - * mina.linear - [ method ] - ** - * Default linear easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.linear = function (n) { - return n; - }; - /*\ - * mina.easeout - [ method ] - ** - * Easeout easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.easeout = function (n) { - return Math.pow(n, 1.7); - }; - /*\ - * mina.easein - [ method ] - ** - * Easein easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.easein = function (n) { - return Math.pow(n, .48); - }; - /*\ - * mina.easeinout - [ method ] - ** - * Easeinout easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.easeinout = function (n) { - if (n == 1) { - return 1; - } - if (n == 0) { - return 0; - } - var q = .48 - n / 1.04, - Q = Math.sqrt(.1734 + q * q), - x = Q - q, - X = Math.pow(Math.abs(x), 1 / 3) * (x < 0 ? -1 : 1), - y = -Q - q, - Y = Math.pow(Math.abs(y), 1 / 3) * (y < 0 ? -1 : 1), - t = X + Y + .5; - return (1 - t) * 3 * t * t + t * t * t; - }; - /*\ - * mina.backin - [ method ] - ** - * Backin easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.backin = function (n) { - if (n == 1) { - return 1; - } - var s = 1.70158; - return n * n * ((s + 1) * n - s); - }; - /*\ - * mina.backout - [ method ] - ** - * Backout easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.backout = function (n) { - if (n == 0) { - return 0; - } - n = n - 1; - var s = 1.70158; - return n * n * ((s + 1) * n + s) + 1; - }; - /*\ - * mina.elastic - [ method ] - ** - * Elastic easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.elastic = function (n) { - if (n == !!n) { - return n; - } - return Math.pow(2, -10 * n) * Math.sin((n - .075) * - (2 * Math.PI) / .3) + 1; - }; - /*\ - * mina.bounce - [ method ] - ** - * Bounce easing - - n (number) input 0..1 - = (number) output 0..1 - \*/ - mina.bounce = function (n) { - var s = 7.5625, - p = 2.75, - l; - if (n < (1 / p)) { - l = s * n * n; - } else { - if (n < (2 / p)) { - n -= (1.5 / p); - l = s * n * n + .75; - } else { - if (n < (2.5 / p)) { - n -= (2.25 / p); - l = s * n * n + .9375; - } else { - n -= (2.625 / p); - l = s * n * n + .984375; - } - } - } - return l; - }; - window.mina = mina; - return mina; - })(typeof eve == "undefined" ? function () {} : eve); - // Copyright (c) 2013 - 2015 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - - var Snap = (function(root) { - Snap.version = "0.4.0"; - /*\ - * Snap - [ method ] - ** - * Creates a drawing surface or wraps existing SVG element. - ** - - width (number|string) width of surface - - height (number|string) height of surface - * or - - DOM (SVGElement) element to be wrapped into Snap structure - * or - - array (array) array of elements (will return set of elements) - * or - - query (string) CSS query selector - = (object) @Element - \*/ - function Snap(w, h) { - if (w) { - if (w.nodeType) { - return wrap(w); - } - if (is(w, "array") && Snap.set) { - return Snap.set.apply(Snap, w); - } - if (w instanceof Element) { - return w; - } - if (h == null) { - w = glob.doc.querySelector(String(w)); - return wrap(w); - } - } - w = w == null ? "100%" : w; - h = h == null ? "100%" : h; - return new Paper(w, h); - } - Snap.toString = function () { - return "Snap v" + this.version; - }; - Snap._ = {}; - var glob = { - win: root.window, - doc: root.window.document - }; - Snap._.glob = glob; - var has = "hasOwnProperty", - Str = String, - toFloat = parseFloat, - toInt = parseInt, - math = Math, - mmax = math.max, - mmin = math.min, - abs = math.abs, - pow = math.pow, - PI = math.PI, - round = math.round, - E = "", - S = " ", - objectToString = Object.prototype.toString, - ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, - colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\))\s*$/i, - bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, - reURLValue = /^url\(#?([^)]+)\)$/, - separator = Snap._.separator = /[,\s]+/, - whitespace = /[\s]/g, - commaSpaces = /[\s]*,[\s]*/, - hsrg = {hs: 1, rg: 1}, - pathCommand = /([a-z])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?[\s]*)+)/ig, - tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?[\s]*)+)/ig, - pathValues = /(-?\d*\.?\d*(?:e[\-+]?\\d+)?)[\s]*,?[\s]*/ig, - idgen = 0, - idprefix = "S" + (+new Date).toString(36), - ID = function (el) { - return (el && el.type ? el.type : E) + idprefix + (idgen++).toString(36); - }, - xlink = "http://www.w3.org/1999/xlink", - xmlns = "http://www.w3.org/2000/svg", - hub = {}, - URL = Snap.url = function (url) { - return "url('#" + url + "')"; - }; - - function $(el, attr) { - if (attr) { - if (el == "#text") { - el = glob.doc.createTextNode(attr.text || attr["#text"] || ""); - } - if (el == "#comment") { - el = glob.doc.createComment(attr.text || attr["#text"] || ""); - } - if (typeof el == "string") { - el = $(el); - } - if (typeof attr == "string") { - if (el.nodeType == 1) { - if (attr.substring(0, 6) == "xlink:") { - return el.getAttributeNS(xlink, attr.substring(6)); - } - if (attr.substring(0, 4) == "xml:") { - return el.getAttributeNS(xmlns, attr.substring(4)); - } - return el.getAttribute(attr); - } else if (attr == "text") { - return el.nodeValue; - } else { - return null; - } - } - if (el.nodeType == 1) { - for (var key in attr) if (attr[has](key)) { - var val = Str(attr[key]); - if (val) { - if (key.substring(0, 6) == "xlink:") { - el.setAttributeNS(xlink, key.substring(6), val); - } else if (key.substring(0, 4) == "xml:") { - el.setAttributeNS(xmlns, key.substring(4), val); - } else { - el.setAttribute(key, val); - } - } else { - el.removeAttribute(key); - } - } - } else if ("text" in attr) { - el.nodeValue = attr.text; - } - } else { - el = glob.doc.createElementNS(xmlns, el); - } - return el; - } - Snap._.$ = $; - Snap._.id = ID; - function getAttrs(el) { - var attrs = el.attributes, - name, - out = {}; - for (var i = 0; i < attrs.length; i++) { - if (attrs[i].namespaceURI == xlink) { - name = "xlink:"; - } else { - name = ""; - } - name += attrs[i].name; - out[name] = attrs[i].textContent; - } - return out; - } - function is(o, type) { - type = Str.prototype.toLowerCase.call(type); - if (type == "finite") { - return isFinite(o); - } - if (type == "array" && - (o instanceof Array || Array.isArray && Array.isArray(o))) { - return true; - } - return (type == "null" && o === null) || - (type == typeof o && o !== null) || - (type == "object" && o === Object(o)) || - objectToString.call(o).slice(8, -1).toLowerCase() == type; - } - /*\ - * Snap.format - [ method ] - ** - * Replaces construction of type `{}` to the corresponding argument - ** - - token (string) string to format - - json (object) object which properties are used as a replacement - = (string) formatted string - > Usage - | // this draws a rectangular shape equivalent to "M10,20h40v50h-40z" - | paper.path(Snap.format("M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z", { - | x: 10, - | y: 20, - | dim: { - | width: 40, - | height: 50, - | "negative width": -40 - | } - | })); - \*/ - Snap.format = (function () { - var tokenRegex = /\{([^\}]+)\}/g, - objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties - replacer = function (all, key, obj) { - var res = obj; - key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) { - name = name || quotedName; - if (res) { - if (name in res) { - res = res[name]; - } - typeof res == "function" && isFunc && (res = res()); - } - }); - res = (res == null || res == obj ? all : res) + ""; - return res; - }; - return function (str, obj) { - return Str(str).replace(tokenRegex, function (all, key) { - return replacer(all, key, obj); - }); - }; - })(); - function clone(obj) { - if (typeof obj == "function" || Object(obj) !== obj) { - return obj; - } - var res = new obj.constructor; - for (var key in obj) if (obj[has](key)) { - res[key] = clone(obj[key]); - } - return res; - } - Snap._.clone = clone; - function repush(array, item) { - for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) { - return array.push(array.splice(i, 1)[0]); - } - } - function cacher(f, scope, postprocessor) { - function newf() { - var arg = Array.prototype.slice.call(arguments, 0), - args = arg.join("\u2400"), - cache = newf.cache = newf.cache || {}, - count = newf.count = newf.count || []; - if (cache[has](args)) { - repush(count, args); - return postprocessor ? postprocessor(cache[args]) : cache[args]; - } - count.length >= 1e3 && delete cache[count.shift()]; - count.push(args); - cache[args] = f.apply(scope, arg); - return postprocessor ? postprocessor(cache[args]) : cache[args]; - } - return newf; - } - Snap._.cacher = cacher; - function angle(x1, y1, x2, y2, x3, y3) { - if (x3 == null) { - var x = x1 - x2, - y = y1 - y2; - if (!x && !y) { - return 0; - } - return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; - } else { - return angle(x1, y1, x3, y3) - angle(x2, y2, x3, y3); - } - } - function rad(deg) { - return deg % 360 * PI / 180; - } - function deg(rad) { - return rad * 180 / PI % 360; - } - function x_y() { - return this.x + S + this.y; - } - function x_y_w_h() { - return this.x + S + this.y + S + this.width + " \xd7 " + this.height; - } - - /*\ - * Snap.rad - [ method ] - ** - * Transform angle to radians - - deg (number) angle in degrees - = (number) angle in radians - \*/ - Snap.rad = rad; - /*\ - * Snap.deg - [ method ] - ** - * Transform angle to degrees - - rad (number) angle in radians - = (number) angle in degrees - \*/ - Snap.deg = deg; - /*\ - * Snap.sin - [ method ] - ** - * Equivalent to `Math.sin()` only works with degrees, not radians. - - angle (number) angle in degrees - = (number) sin - \*/ - Snap.sin = function (angle) { - return math.sin(Snap.rad(angle)); - }; - /*\ - * Snap.tan - [ method ] - ** - * Equivalent to `Math.tan()` only works with degrees, not radians. - - angle (number) angle in degrees - = (number) tan - \*/ - Snap.tan = function (angle) { - return math.tan(Snap.rad(angle)); - }; - /*\ - * Snap.cos - [ method ] - ** - * Equivalent to `Math.cos()` only works with degrees, not radians. - - angle (number) angle in degrees - = (number) cos - \*/ - Snap.cos = function (angle) { - return math.cos(Snap.rad(angle)); - }; - /*\ - * Snap.asin - [ method ] - ** - * Equivalent to `Math.asin()` only works with degrees, not radians. - - num (number) value - = (number) asin in degrees - \*/ - Snap.asin = function (num) { - return Snap.deg(math.asin(num)); - }; - /*\ - * Snap.acos - [ method ] - ** - * Equivalent to `Math.acos()` only works with degrees, not radians. - - num (number) value - = (number) acos in degrees - \*/ - Snap.acos = function (num) { - return Snap.deg(math.acos(num)); - }; - /*\ - * Snap.atan - [ method ] - ** - * Equivalent to `Math.atan()` only works with degrees, not radians. - - num (number) value - = (number) atan in degrees - \*/ - Snap.atan = function (num) { - return Snap.deg(math.atan(num)); - }; - /*\ - * Snap.atan2 - [ method ] - ** - * Equivalent to `Math.atan2()` only works with degrees, not radians. - - num (number) value - = (number) atan2 in degrees - \*/ - Snap.atan2 = function (num) { - return Snap.deg(math.atan2(num)); - }; - /*\ - * Snap.angle - [ method ] - ** - * Returns an angle between two or three points - > Parameters - - x1 (number) x coord of first point - - y1 (number) y coord of first point - - x2 (number) x coord of second point - - y2 (number) y coord of second point - - x3 (number) #optional x coord of third point - - y3 (number) #optional y coord of third point - = (number) angle in degrees - \*/ - Snap.angle = angle; - /*\ - * Snap.len - [ method ] - ** - * Returns distance between two points - > Parameters - - x1 (number) x coord of first point - - y1 (number) y coord of first point - - x2 (number) x coord of second point - - y2 (number) y coord of second point - = (number) distance - \*/ - Snap.len = function (x1, y1, x2, y2) { - return Math.sqrt(Snap.len2(x1, y1, x2, y2)); - }; - /*\ - * Snap.len2 - [ method ] - ** - * Returns squared distance between two points - > Parameters - - x1 (number) x coord of first point - - y1 (number) y coord of first point - - x2 (number) x coord of second point - - y2 (number) y coord of second point - = (number) distance - \*/ - Snap.len2 = function (x1, y1, x2, y2) { - return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); - }; - /*\ - * Snap.closestPoint - [ method ] - ** - * Returns closest point to a given one on a given path. - > Parameters - - path (Element) path element - - x (number) x coord of a point - - y (number) y coord of a point - = (object) in format - { - x (number) x coord of the point on the path - y (number) y coord of the point on the path - length (number) length of the path to the point - distance (number) distance from the given point to the path - } - \*/ - // Copied from http://bl.ocks.org/mbostock/8027637 - Snap.closestPoint = function (path, x, y) { - function distance2(p) { - var dx = p.x - x, - dy = p.y - y; - return dx * dx + dy * dy; - } - var pathNode = path.node, - pathLength = pathNode.getTotalLength(), - precision = pathLength / pathNode.pathSegList.numberOfItems * .125, - best, - bestLength, - bestDistance = Infinity; - - // linear scan for coarse approximation - for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) { - if ((scanDistance = distance2(scan = pathNode.getPointAtLength(scanLength))) < bestDistance) { - best = scan, bestLength = scanLength, bestDistance = scanDistance; - } - } - - // binary search for precise estimate - precision *= .5; - while (precision > .5) { - var before, - after, - beforeLength, - afterLength, - beforeDistance, - afterDistance; - if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = pathNode.getPointAtLength(beforeLength))) < bestDistance) { - best = before, bestLength = beforeLength, bestDistance = beforeDistance; - } else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = pathNode.getPointAtLength(afterLength))) < bestDistance) { - best = after, bestLength = afterLength, bestDistance = afterDistance; - } else { - precision *= .5; - } - } - - best = { - x: best.x, - y: best.y, - length: bestLength, - distance: Math.sqrt(bestDistance) - }; - return best; - } - /*\ - * Snap.is - [ method ] - ** - * Handy replacement for the `typeof` operator - - o (…) any object or primitive - - type (string) name of the type, e.g., `string`, `function`, `number`, etc. - = (boolean) `true` if given value is of given type - \*/ - Snap.is = is; - /*\ - * Snap.snapTo - [ method ] - ** - * Snaps given value to given grid - - values (array|number) given array of values or step of the grid - - value (number) value to adjust - - tolerance (number) #optional maximum distance to the target value that would trigger the snap. Default is `10`. - = (number) adjusted value - \*/ - Snap.snapTo = function (values, value, tolerance) { - tolerance = is(tolerance, "finite") ? tolerance : 10; - if (is(values, "array")) { - var i = values.length; - while (i--) if (abs(values[i] - value) <= tolerance) { - return values[i]; - } - } else { - values = +values; - var rem = value % values; - if (rem < tolerance) { - return value - rem; - } - if (rem > values - tolerance) { - return value - rem + values; - } - } - return value; - }; - // Colour - /*\ - * Snap.getRGB - [ method ] - ** - * Parses color string as RGB object - - color (string) color string in one of the following formats: - # - * Note that `%` can be used any time: `rgb(20%, 255, 50%)`. - = (object) RGB object in the following format: - o { - o r (number) red, - o g (number) green, - o b (number) blue, - o hex (string) color in HTML/CSS format: #••••••, - o error (boolean) true if string can't be parsed - o } - \*/ - Snap.getRGB = cacher(function (colour) { - if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { - return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: rgbtoString}; - } - if (colour == "none") { - return {r: -1, g: -1, b: -1, hex: "none", toString: rgbtoString}; - } - !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); - if (!colour) { - return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: rgbtoString}; - } - var res, - red, - green, - blue, - opacity, - t, - values, - rgb = colour.match(colourRegExp); - if (rgb) { - if (rgb[2]) { - blue = toInt(rgb[2].substring(5), 16); - green = toInt(rgb[2].substring(3, 5), 16); - red = toInt(rgb[2].substring(1, 3), 16); - } - if (rgb[3]) { - blue = toInt((t = rgb[3].charAt(3)) + t, 16); - green = toInt((t = rgb[3].charAt(2)) + t, 16); - red = toInt((t = rgb[3].charAt(1)) + t, 16); - } - if (rgb[4]) { - values = rgb[4].split(commaSpaces); - red = toFloat(values[0]); - values[0].slice(-1) == "%" && (red *= 2.55); - green = toFloat(values[1]); - values[1].slice(-1) == "%" && (green *= 2.55); - blue = toFloat(values[2]); - values[2].slice(-1) == "%" && (blue *= 2.55); - rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); - values[3] && values[3].slice(-1) == "%" && (opacity /= 100); - } - if (rgb[5]) { - values = rgb[5].split(commaSpaces); - red = toFloat(values[0]); - values[0].slice(-1) == "%" && (red /= 100); - green = toFloat(values[1]); - values[1].slice(-1) == "%" && (green /= 100); - blue = toFloat(values[2]); - values[2].slice(-1) == "%" && (blue /= 100); - (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); - rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); - values[3] && values[3].slice(-1) == "%" && (opacity /= 100); - return Snap.hsb2rgb(red, green, blue, opacity); - } - if (rgb[6]) { - values = rgb[6].split(commaSpaces); - red = toFloat(values[0]); - values[0].slice(-1) == "%" && (red /= 100); - green = toFloat(values[1]); - values[1].slice(-1) == "%" && (green /= 100); - blue = toFloat(values[2]); - values[2].slice(-1) == "%" && (blue /= 100); - (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); - rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); - values[3] && values[3].slice(-1) == "%" && (opacity /= 100); - return Snap.hsl2rgb(red, green, blue, opacity); - } - red = mmin(math.round(red), 255); - green = mmin(math.round(green), 255); - blue = mmin(math.round(blue), 255); - opacity = mmin(mmax(opacity, 0), 1); - rgb = {r: red, g: green, b: blue, toString: rgbtoString}; - rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1); - rgb.opacity = is(opacity, "finite") ? opacity : 1; - return rgb; - } - return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: rgbtoString}; - }, Snap); - /*\ - * Snap.hsb - [ method ] - ** - * Converts HSB values to a hex representation of the color - - h (number) hue - - s (number) saturation - - b (number) value or brightness - = (string) hex representation of the color - \*/ - Snap.hsb = cacher(function (h, s, b) { - return Snap.hsb2rgb(h, s, b).hex; - }); - /*\ - * Snap.hsl - [ method ] - ** - * Converts HSL values to a hex representation of the color - - h (number) hue - - s (number) saturation - - l (number) luminosity - = (string) hex representation of the color - \*/ - Snap.hsl = cacher(function (h, s, l) { - return Snap.hsl2rgb(h, s, l).hex; - }); - /*\ - * Snap.rgb - [ method ] - ** - * Converts RGB values to a hex representation of the color - - r (number) red - - g (number) green - - b (number) blue - = (string) hex representation of the color - \*/ - Snap.rgb = cacher(function (r, g, b, o) { - if (is(o, "finite")) { - var round = math.round; - return "rgba(" + [round(r), round(g), round(b), +o.toFixed(2)] + ")"; - } - return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); - }); - var toHex = function (color) { - var i = glob.doc.getElementsByTagName("head")[0] || glob.doc.getElementsByTagName("svg")[0], - red = "rgb(255, 0, 0)"; - toHex = cacher(function (color) { - if (color.toLowerCase() == "red") { - return red; - } - i.style.color = red; - i.style.color = color; - var out = glob.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); - return out == red ? null : out; - }); - return toHex(color); - }, - hsbtoString = function () { - return "hsb(" + [this.h, this.s, this.b] + ")"; - }, - hsltoString = function () { - return "hsl(" + [this.h, this.s, this.l] + ")"; - }, - rgbtoString = function () { - return this.opacity == 1 || this.opacity == null ? - this.hex : - "rgba(" + [this.r, this.g, this.b, this.opacity] + ")"; - }, - prepareRGB = function (r, g, b) { - if (g == null && is(r, "object") && "r" in r && "g" in r && "b" in r) { - b = r.b; - g = r.g; - r = r.r; - } - if (g == null && is(r, string)) { - var clr = Snap.getRGB(r); - r = clr.r; - g = clr.g; - b = clr.b; - } - if (r > 1 || g > 1 || b > 1) { - r /= 255; - g /= 255; - b /= 255; - } - - return [r, g, b]; - }, - packageRGB = function (r, g, b, o) { - r = math.round(r * 255); - g = math.round(g * 255); - b = math.round(b * 255); - var rgb = { - r: r, - g: g, - b: b, - opacity: is(o, "finite") ? o : 1, - hex: Snap.rgb(r, g, b), - toString: rgbtoString - }; - is(o, "finite") && (rgb.opacity = o); - return rgb; - }; - /*\ - * Snap.color - [ method ] - ** - * Parses the color string and returns an object featuring the color's component values - - clr (string) color string in one of the supported formats (see @Snap.getRGB) - = (object) Combined RGB/HSB object in the following format: - o { - o r (number) red, - o g (number) green, - o b (number) blue, - o hex (string) color in HTML/CSS format: #••••••, - o error (boolean) `true` if string can't be parsed, - o h (number) hue, - o s (number) saturation, - o v (number) value (brightness), - o l (number) lightness - o } - \*/ - Snap.color = function (clr) { - var rgb; - if (is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) { - rgb = Snap.hsb2rgb(clr); - clr.r = rgb.r; - clr.g = rgb.g; - clr.b = rgb.b; - clr.opacity = 1; - clr.hex = rgb.hex; - } else if (is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) { - rgb = Snap.hsl2rgb(clr); - clr.r = rgb.r; - clr.g = rgb.g; - clr.b = rgb.b; - clr.opacity = 1; - clr.hex = rgb.hex; - } else { - if (is(clr, "string")) { - clr = Snap.getRGB(clr); - } - if (is(clr, "object") && "r" in clr && "g" in clr && "b" in clr && !("error" in clr)) { - rgb = Snap.rgb2hsl(clr); - clr.h = rgb.h; - clr.s = rgb.s; - clr.l = rgb.l; - rgb = Snap.rgb2hsb(clr); - clr.v = rgb.b; - } else { - clr = {hex: "none"}; - clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1; - clr.error = 1; - } - } - clr.toString = rgbtoString; - return clr; - }; - /*\ - * Snap.hsb2rgb - [ method ] - ** - * Converts HSB values to an RGB object - - h (number) hue - - s (number) saturation - - v (number) value or brightness - = (object) RGB object in the following format: - o { - o r (number) red, - o g (number) green, - o b (number) blue, - o hex (string) color in HTML/CSS format: #•••••• - o } - \*/ - Snap.hsb2rgb = function (h, s, v, o) { - if (is(h, "object") && "h" in h && "s" in h && "b" in h) { - v = h.b; - s = h.s; - o = h.o; - h = h.h; - } - h *= 360; - var R, G, B, X, C; - h = (h % 360) / 60; - C = v * s; - X = C * (1 - abs(h % 2 - 1)); - R = G = B = v - C; - - h = ~~h; - R += [C, X, 0, 0, X, C][h]; - G += [X, C, C, X, 0, 0][h]; - B += [0, 0, X, C, C, X][h]; - return packageRGB(R, G, B, o); - }; - /*\ - * Snap.hsl2rgb - [ method ] - ** - * Converts HSL values to an RGB object - - h (number) hue - - s (number) saturation - - l (number) luminosity - = (object) RGB object in the following format: - o { - o r (number) red, - o g (number) green, - o b (number) blue, - o hex (string) color in HTML/CSS format: #•••••• - o } - \*/ - Snap.hsl2rgb = function (h, s, l, o) { - if (is(h, "object") && "h" in h && "s" in h && "l" in h) { - l = h.l; - s = h.s; - h = h.h; - } - if (h > 1 || s > 1 || l > 1) { - h /= 360; - s /= 100; - l /= 100; - } - h *= 360; - var R, G, B, X, C; - h = (h % 360) / 60; - C = 2 * s * (l < .5 ? l : 1 - l); - X = C * (1 - abs(h % 2 - 1)); - R = G = B = l - C / 2; - - h = ~~h; - R += [C, X, 0, 0, X, C][h]; - G += [X, C, C, X, 0, 0][h]; - B += [0, 0, X, C, C, X][h]; - return packageRGB(R, G, B, o); - }; - /*\ - * Snap.rgb2hsb - [ method ] - ** - * Converts RGB values to an HSB object - - r (number) red - - g (number) green - - b (number) blue - = (object) HSB object in the following format: - o { - o h (number) hue, - o s (number) saturation, - o b (number) brightness - o } - \*/ - Snap.rgb2hsb = function (r, g, b) { - b = prepareRGB(r, g, b); - r = b[0]; - g = b[1]; - b = b[2]; - - var H, S, V, C; - V = mmax(r, g, b); - C = V - mmin(r, g, b); - H = (C == 0 ? null : - V == r ? (g - b) / C : - V == g ? (b - r) / C + 2 : - (r - g) / C + 4 - ); - H = ((H + 360) % 6) * 60 / 360; - S = C == 0 ? 0 : C / V; - return {h: H, s: S, b: V, toString: hsbtoString}; - }; - /*\ - * Snap.rgb2hsl - [ method ] - ** - * Converts RGB values to an HSL object - - r (number) red - - g (number) green - - b (number) blue - = (object) HSL object in the following format: - o { - o h (number) hue, - o s (number) saturation, - o l (number) luminosity - o } - \*/ - Snap.rgb2hsl = function (r, g, b) { - b = prepareRGB(r, g, b); - r = b[0]; - g = b[1]; - b = b[2]; - - var H, S, L, M, m, C; - M = mmax(r, g, b); - m = mmin(r, g, b); - C = M - m; - H = (C == 0 ? null : - M == r ? (g - b) / C : - M == g ? (b - r) / C + 2 : - (r - g) / C + 4); - H = ((H + 360) % 6) * 60 / 360; - L = (M + m) / 2; - S = (C == 0 ? 0 : - L < .5 ? C / (2 * L) : - C / (2 - 2 * L)); - return {h: H, s: S, l: L, toString: hsltoString}; - }; - - // Transformations - /*\ - * Snap.parsePathString - [ method ] - ** - * Utility method - ** - * Parses given path string into an array of arrays of path segments - - pathString (string|array) path string or array of segments (in the last case it is returned straight away) - = (array) array of segments - \*/ - Snap.parsePathString = function (pathString) { - if (!pathString) { - return null; - } - var pth = Snap.path(pathString); - if (pth.arr) { - return Snap.path.clone(pth.arr); - } - - var paramCounts = {a: 7, c: 6, o: 2, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, u: 3, z: 0}, - data = []; - if (is(pathString, "array") && is(pathString[0], "array")) { // rough assumption - data = Snap.path.clone(pathString); - } - if (!data.length) { - Str(pathString).replace(pathCommand, function (a, b, c) { - var params = [], - name = b.toLowerCase(); - c.replace(pathValues, function (a, b) { - b && params.push(+b); - }); - if (name == "m" && params.length > 2) { - data.push([b].concat(params.splice(0, 2))); - name = "l"; - b = b == "m" ? "l" : "L"; - } - if (name == "o" && params.length == 1) { - data.push([b, params[0]]); - } - if (name == "r") { - data.push([b].concat(params)); - } else while (params.length >= paramCounts[name]) { - data.push([b].concat(params.splice(0, paramCounts[name]))); - if (!paramCounts[name]) { - break; - } - } - }); - } - data.toString = Snap.path.toString; - pth.arr = Snap.path.clone(data); - return data; - }; - /*\ - * Snap.parseTransformString - [ method ] - ** - * Utility method - ** - * Parses given transform string into an array of transformations - - TString (string|array) transform string or array of transformations (in the last case it is returned straight away) - = (array) array of transformations - \*/ - var parseTransformString = Snap.parseTransformString = function (TString) { - if (!TString) { - return null; - } - var paramCounts = {r: 3, s: 4, t: 2, m: 6}, - data = []; - if (is(TString, "array") && is(TString[0], "array")) { // rough assumption - data = Snap.path.clone(TString); - } - if (!data.length) { - Str(TString).replace(tCommand, function (a, b, c) { - var params = [], - name = b.toLowerCase(); - c.replace(pathValues, function (a, b) { - b && params.push(+b); - }); - data.push([b].concat(params)); - }); - } - data.toString = Snap.path.toString; - return data; - }; - function svgTransform2string(tstr) { - var res = []; - tstr = tstr.replace(/(?:^|\s)(\w+)\(([^)]+)\)/g, function (all, name, params) { - params = params.split(/\s*,\s*|\s+/); - if (name == "rotate" && params.length == 1) { - params.push(0, 0); - } - if (name == "scale") { - if (params.length > 2) { - params = params.slice(0, 2); - } else if (params.length == 2) { - params.push(0, 0); - } - if (params.length == 1) { - params.push(params[0], 0, 0); - } - } - if (name == "skewX") { - res.push(["m", 1, 0, math.tan(rad(params[0])), 1, 0, 0]); - } else if (name == "skewY") { - res.push(["m", 1, math.tan(rad(params[0])), 0, 1, 0, 0]); - } else { - res.push([name.charAt(0)].concat(params)); - } - return all; - }); - return res; - } - Snap._.svgTransform2string = svgTransform2string; - Snap._.rgTransform = /^[a-z][\s]*-?\.?\d/i; - function transform2matrix(tstr, bbox) { - var tdata = parseTransformString(tstr), - m = new Snap.Matrix; - if (tdata) { - for (var i = 0, ii = tdata.length; i < ii; i++) { - var t = tdata[i], - tlen = t.length, - command = Str(t[0]).toLowerCase(), - absolute = t[0] != command, - inver = absolute ? m.invert() : 0, - x1, - y1, - x2, - y2, - bb; - if (command == "t" && tlen == 2){ - m.translate(t[1], 0); - } else if (command == "t" && tlen == 3) { - if (absolute) { - x1 = inver.x(0, 0); - y1 = inver.y(0, 0); - x2 = inver.x(t[1], t[2]); - y2 = inver.y(t[1], t[2]); - m.translate(x2 - x1, y2 - y1); - } else { - m.translate(t[1], t[2]); - } - } else if (command == "r") { - if (tlen == 2) { - bb = bb || bbox; - m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2); - } else if (tlen == 4) { - if (absolute) { - x2 = inver.x(t[2], t[3]); - y2 = inver.y(t[2], t[3]); - m.rotate(t[1], x2, y2); - } else { - m.rotate(t[1], t[2], t[3]); - } - } - } else if (command == "s") { - if (tlen == 2 || tlen == 3) { - bb = bb || bbox; - m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2); - } else if (tlen == 4) { - if (absolute) { - x2 = inver.x(t[2], t[3]); - y2 = inver.y(t[2], t[3]); - m.scale(t[1], t[1], x2, y2); - } else { - m.scale(t[1], t[1], t[2], t[3]); - } - } else if (tlen == 5) { - if (absolute) { - x2 = inver.x(t[3], t[4]); - y2 = inver.y(t[3], t[4]); - m.scale(t[1], t[2], x2, y2); - } else { - m.scale(t[1], t[2], t[3], t[4]); - } - } - } else if (command == "m" && tlen == 7) { - m.add(t[1], t[2], t[3], t[4], t[5], t[6]); - } - } - } - return m; - } - Snap._.transform2matrix = transform2matrix; - Snap._unit2px = unit2px; - var contains = glob.doc.contains || glob.doc.compareDocumentPosition ? - function (a, b) { - var adown = a.nodeType == 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a == bup || !!(bup && bup.nodeType == 1 && ( - adown.contains ? - adown.contains(bup) : - a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16 - )); - } : - function (a, b) { - if (b) { - while (b) { - b = b.parentNode; - if (b == a) { - return true; - } - } - } - return false; - }; - function getSomeDefs(el) { - var p = (el.node.ownerSVGElement && wrap(el.node.ownerSVGElement)) || - (el.node.parentNode && wrap(el.node.parentNode)) || - Snap.select("svg") || - Snap(0, 0), - pdefs = p.select("defs"), - defs = pdefs == null ? false : pdefs.node; - if (!defs) { - defs = make("defs", p.node).node; - } - return defs; - } - function getSomeSVG(el) { - return el.node.ownerSVGElement && wrap(el.node.ownerSVGElement) || Snap.select("svg"); - } - Snap._.getSomeDefs = getSomeDefs; - Snap._.getSomeSVG = getSomeSVG; - function unit2px(el, name, value) { - var svg = getSomeSVG(el).node, - out = {}, - mgr = svg.querySelector(".svg---mgr"); - if (!mgr) { - mgr = $("rect"); - $(mgr, {x: -9e9, y: -9e9, width: 10, height: 10, "class": "svg---mgr", fill: "none"}); - svg.appendChild(mgr); - } - function getW(val) { - if (val == null) { - return E; - } - if (val == +val) { - return val; - } - $(mgr, {width: val}); - try { - return mgr.getBBox().width; - } catch (e) { - return 0; - } - } - function getH(val) { - if (val == null) { - return E; - } - if (val == +val) { - return val; - } - $(mgr, {height: val}); - try { - return mgr.getBBox().height; - } catch (e) { - return 0; - } - } - function set(nam, f) { - if (name == null) { - out[nam] = f(el.attr(nam) || 0); - } else if (nam == name) { - out = f(value == null ? el.attr(nam) || 0 : value); - } - } - switch (el.type) { - case "rect": - set("rx", getW); - set("ry", getH); - case "image": - set("width", getW); - set("height", getH); - case "text": - set("x", getW); - set("y", getH); - break; - case "circle": - set("cx", getW); - set("cy", getH); - set("r", getW); - break; - case "ellipse": - set("cx", getW); - set("cy", getH); - set("rx", getW); - set("ry", getH); - break; - case "line": - set("x1", getW); - set("x2", getW); - set("y1", getH); - set("y2", getH); - break; - case "marker": - set("refX", getW); - set("markerWidth", getW); - set("refY", getH); - set("markerHeight", getH); - break; - case "radialGradient": - set("fx", getW); - set("fy", getH); - break; - case "tspan": - set("dx", getW); - set("dy", getH); - break; - default: - set(name, getW); - } - svg.removeChild(mgr); - return out; - } - /*\ - * Snap.select - [ method ] - ** - * Wraps a DOM element specified by CSS selector as @Element - - query (string) CSS selector of the element - = (Element) the current element - \*/ - Snap.select = function (query) { - query = Str(query).replace(/([^\\]):/g, "$1\\:"); - return wrap(glob.doc.querySelector(query)); - }; - /*\ - * Snap.selectAll - [ method ] - ** - * Wraps DOM elements specified by CSS selector as set or array of @Element - - query (string) CSS selector of the element - = (Element) the current element - \*/ - Snap.selectAll = function (query) { - var nodelist = glob.doc.querySelectorAll(query), - set = (Snap.set || Array)(); - for (var i = 0; i < nodelist.length; i++) { - set.push(wrap(nodelist[i])); - } - return set; - }; - - function add2group(list) { - if (!is(list, "array")) { - list = Array.prototype.slice.call(arguments, 0); - } - var i = 0, - j = 0, - node = this.node; - while (this[i]) delete this[i++]; - for (i = 0; i < list.length; i++) { - if (list[i].type == "set") { - list[i].forEach(function (el) { - node.appendChild(el.node); - }); - } else { - node.appendChild(list[i].node); - } - } - var children = node.childNodes; - for (i = 0; i < children.length; i++) { - this[j++] = wrap(children[i]); - } - return this; - } - // Hub garbage collector every 10s - setInterval(function () { - for (var key in hub) if (hub[has](key)) { - var el = hub[key], - node = el.node; - if (el.type != "svg" && !node.ownerSVGElement || el.type == "svg" && (!node.parentNode || "ownerSVGElement" in node.parentNode && !node.ownerSVGElement)) { - delete hub[key]; - } - } - }, 1e4); - function Element(el) { - if (el.snap in hub) { - return hub[el.snap]; - } - var svg; - try { - svg = el.ownerSVGElement; - } catch(e) {} - /*\ - * Element.node - [ property (object) ] - ** - * Gives you a reference to the DOM object, so you can assign event handlers or just mess around. - > Usage - | // draw a circle at coordinate 10,10 with radius of 10 - | var c = paper.circle(10, 10, 10); - | c.node.onclick = function () { - | c.attr("fill", "red"); - | }; - \*/ - this.node = el; - if (svg) { - this.paper = new Paper(svg); - } - /*\ - * Element.type - [ property (string) ] - ** - * SVG tag name of the given element. - \*/ - this.type = el.tagName || el.nodeName; - var id = this.id = ID(this); - this.anims = {}; - this._ = { - transform: [] - }; - el.snap = id; - hub[id] = this; - if (this.type == "g") { - this.add = add2group; - } - if (this.type in {g: 1, mask: 1, pattern: 1, symbol: 1}) { - for (var method in Paper.prototype) if (Paper.prototype[has](method)) { - this[method] = Paper.prototype[method]; - } - } - } - /*\ - * Element.attr - [ method ] - ** - * Gets or sets given attributes of the element. - ** - - params (object) contains key-value pairs of attributes you want to set - * or - - param (string) name of the attribute - = (Element) the current element - * or - = (string) value of attribute - > Usage - | el.attr({ - | fill: "#fc0", - | stroke: "#000", - | strokeWidth: 2, // CamelCase... - | "fill-opacity": 0.5, // or dash-separated names - | width: "*=2" // prefixed values - | }); - | console.log(el.attr("fill")); // #fc0 - * Prefixed values in format `"+=10"` supported. All four operations - * (`+`, `-`, `*` and `/`) could be used. Optionally you can use units for `+` - * and `-`: `"+=2em"`. - \*/ - Element.prototype.attr = function (params, value) { - var el = this, - node = el.node; - if (!params) { - if (node.nodeType != 1) { - return { - text: node.nodeValue - }; - } - var attr = node.attributes, - out = {}; - for (var i = 0, ii = attr.length; i < ii; i++) { - out[attr[i].nodeName] = attr[i].nodeValue; - } - return out; - } - if (is(params, "string")) { - if (arguments.length > 1) { - var json = {}; - json[params] = value; - params = json; - } else { - return eve("snap.util.getattr." + params, el).firstDefined(); - } - } - for (var att in params) { - if (params[has](att)) { - eve("snap.util.attr." + att, el, params[att]); - } - } - return el; - }; - /*\ - * Snap.parse - [ method ] - ** - * Parses SVG fragment and converts it into a @Fragment - ** - - svg (string) SVG string - = (Fragment) the @Fragment - \*/ - Snap.parse = function (svg) { - var f = glob.doc.createDocumentFragment(), - full = true, - div = glob.doc.createElement("div"); - svg = Str(svg); - if (!svg.match(/^\s*<\s*svg(?:\s|>)/)) { - svg = "" + svg + ""; - full = false; - } - div.innerHTML = svg; - svg = div.getElementsByTagName("svg")[0]; - if (svg) { - if (full) { - f = svg; - } else { - while (svg.firstChild) { - f.appendChild(svg.firstChild); - } - } - } - return new Fragment(f); - }; - function Fragment(frag) { - this.node = frag; - } - /*\ - * Snap.fragment - [ method ] - ** - * Creates a DOM fragment from a given list of elements or strings - ** - - varargs (…) SVG string - = (Fragment) the @Fragment - \*/ - Snap.fragment = function () { - var args = Array.prototype.slice.call(arguments, 0), - f = glob.doc.createDocumentFragment(); - for (var i = 0, ii = args.length; i < ii; i++) { - var item = args[i]; - if (item.node && item.node.nodeType) { - f.appendChild(item.node); - } - if (item.nodeType) { - f.appendChild(item); - } - if (typeof item == "string") { - f.appendChild(Snap.parse(item).node); - } - } - return new Fragment(f); - }; - - function make(name, parent) { - var res = $(name); - parent.appendChild(res); - var el = wrap(res); - return el; - } - function Paper(w, h) { - var res, - desc, - defs, - proto = Paper.prototype; - if (w && w.tagName == "svg") { - if (w.snap in hub) { - return hub[w.snap]; - } - var doc = w.ownerDocument; - res = new Element(w); - desc = w.getElementsByTagName("desc")[0]; - defs = w.getElementsByTagName("defs")[0]; - if (!desc) { - desc = $("desc"); - desc.appendChild(doc.createTextNode("Created with Snap")); - res.node.appendChild(desc); - } - if (!defs) { - defs = $("defs"); - res.node.appendChild(defs); - } - res.defs = defs; - for (var key in proto) if (proto[has](key)) { - res[key] = proto[key]; - } - res.paper = res.root = res; - } else { - res = make("svg", glob.doc.body); - $(res.node, { - height: h, - version: 1.1, - width: w, - xmlns: xmlns - }); - } - return res; - } - function wrap(dom) { - if (!dom) { - return dom; - } - if (dom instanceof Element || dom instanceof Fragment) { - return dom; - } - if (dom.tagName && dom.tagName.toLowerCase() == "svg") { - return new Paper(dom); - } - if (dom.tagName && dom.tagName.toLowerCase() == "object" && dom.type == "image/svg+xml") { - return new Paper(dom.contentDocument.getElementsByTagName("svg")[0]); - } - return new Element(dom); - } - - Snap._.make = make; - Snap._.wrap = wrap; - /*\ - * Paper.el - [ method ] - ** - * Creates an element on paper with a given name and no attributes - ** - - name (string) tag name - - attr (object) attributes - = (Element) the current element - > Usage - | var c = paper.circle(10, 10, 10); // is the same as... - | var c = paper.el("circle").attr({ - | cx: 10, - | cy: 10, - | r: 10 - | }); - | // and the same as - | var c = paper.el("circle", { - | cx: 10, - | cy: 10, - | r: 10 - | }); - \*/ - Paper.prototype.el = function (name, attr) { - var el = make(name, this.node); - attr && el.attr(attr); - return el; - }; - /*\ - * Element.children - [ method ] - ** - * Returns array of all the children of the element. - = (array) array of Elements - \*/ - Element.prototype.children = function () { - var out = [], - ch = this.node.childNodes; - for (var i = 0, ii = ch.length; i < ii; i++) { - out[i] = Snap(ch[i]); - } - return out; - }; - function jsonFiller(root, o) { - for (var i = 0, ii = root.length; i < ii; i++) { - var item = { - type: root[i].type, - attr: root[i].attr() - }, - children = root[i].children(); - o.push(item); - if (children.length) { - jsonFiller(children, item.childNodes = []); - } - } - } - /*\ - * Element.toJSON - [ method ] - ** - * Returns object representation of the given element and all its children. - = (object) in format - o { - o type (string) this.type, - o attr (object) attributes map, - o childNodes (array) optional array of children in the same format - o } - \*/ - Element.prototype.toJSON = function () { - var out = []; - jsonFiller([this], out); - return out[0]; - }; - // default - eve.on("snap.util.getattr", function () { - var att = eve.nt(); - att = att.substring(att.lastIndexOf(".") + 1); - var css = att.replace(/[A-Z]/g, function (letter) { - return "-" + letter.toLowerCase(); - }); - if (cssAttr[has](css)) { - return this.node.ownerDocument.defaultView.getComputedStyle(this.node, null).getPropertyValue(css); - } else { - return $(this.node, att); - } - }); - var cssAttr = { - "alignment-baseline": 0, - "baseline-shift": 0, - "clip": 0, - "clip-path": 0, - "clip-rule": 0, - "color": 0, - "color-interpolation": 0, - "color-interpolation-filters": 0, - "color-profile": 0, - "color-rendering": 0, - "cursor": 0, - "direction": 0, - "display": 0, - "dominant-baseline": 0, - "enable-background": 0, - "fill": 0, - "fill-opacity": 0, - "fill-rule": 0, - "filter": 0, - "flood-color": 0, - "flood-opacity": 0, - "font": 0, - "font-family": 0, - "font-size": 0, - "font-size-adjust": 0, - "font-stretch": 0, - "font-style": 0, - "font-variant": 0, - "font-weight": 0, - "glyph-orientation-horizontal": 0, - "glyph-orientation-vertical": 0, - "image-rendering": 0, - "kerning": 0, - "letter-spacing": 0, - "lighting-color": 0, - "marker": 0, - "marker-end": 0, - "marker-mid": 0, - "marker-start": 0, - "mask": 0, - "opacity": 0, - "overflow": 0, - "pointer-events": 0, - "shape-rendering": 0, - "stop-color": 0, - "stop-opacity": 0, - "stroke": 0, - "stroke-dasharray": 0, - "stroke-dashoffset": 0, - "stroke-linecap": 0, - "stroke-linejoin": 0, - "stroke-miterlimit": 0, - "stroke-opacity": 0, - "stroke-width": 0, - "text-anchor": 0, - "text-decoration": 0, - "text-rendering": 0, - "unicode-bidi": 0, - "visibility": 0, - "word-spacing": 0, - "writing-mode": 0 - }; - - eve.on("snap.util.attr", function (value) { - var att = eve.nt(), - attr = {}; - att = att.substring(att.lastIndexOf(".") + 1); - attr[att] = value; - var style = att.replace(/-(\w)/gi, function (all, letter) { - return letter.toUpperCase(); - }), - css = att.replace(/[A-Z]/g, function (letter) { - return "-" + letter.toLowerCase(); - }); - if (cssAttr[has](css)) { - this.node.style[style] = value == null ? E : value; - } else { - $(this.node, attr); - } - }); - (function (proto) {}(Paper.prototype)); - - // simple ajax - /*\ - * Snap.ajax - [ method ] - ** - * Simple implementation of Ajax - ** - - url (string) URL - - postData (object|string) data for post request - - callback (function) callback - - scope (object) #optional scope of callback - * or - - url (string) URL - - callback (function) callback - - scope (object) #optional scope of callback - = (XMLHttpRequest) the XMLHttpRequest object, just in case - \*/ - Snap.ajax = function (url, postData, callback, scope){ - var req = new XMLHttpRequest, - id = ID(); - if (req) { - if (is(postData, "function")) { - scope = callback; - callback = postData; - postData = null; - } else if (is(postData, "object")) { - var pd = []; - for (var key in postData) if (postData.hasOwnProperty(key)) { - pd.push(encodeURIComponent(key) + "=" + encodeURIComponent(postData[key])); - } - postData = pd.join("&"); - } - req.open((postData ? "POST" : "GET"), url, true); - if (postData) { - req.setRequestHeader("X-Requested-With", "XMLHttpRequest"); - req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - } - if (callback) { - eve.once("snap.ajax." + id + ".0", callback); - eve.once("snap.ajax." + id + ".200", callback); - eve.once("snap.ajax." + id + ".304", callback); - } - req.onreadystatechange = function() { - if (req.readyState != 4) return; - eve("snap.ajax." + id + "." + req.status, scope, req); - }; - if (req.readyState == 4) { - return req; - } - req.send(postData); - return req; - } - }; - /*\ - * Snap.load - [ method ] - ** - * Loads external SVG file as a @Fragment (see @Snap.ajax for more advanced AJAX) - ** - - url (string) URL - - callback (function) callback - - scope (object) #optional scope of callback - \*/ - Snap.load = function (url, callback, scope) { - Snap.ajax(url, function (req) { - var f = Snap.parse(req.responseText); - scope ? callback.call(scope, f) : callback(f); - }); - }; - var getOffset = function (elem) { - var box = elem.getBoundingClientRect(), - doc = elem.ownerDocument, - body = doc.body, - docElem = doc.documentElement, - clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, - top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop, - left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft; - return { - y: top, - x: left - }; - }; - /*\ - * Snap.getElementByPoint - [ method ] - ** - * Returns you topmost element under given point. - ** - = (object) Snap element object - - x (number) x coordinate from the top left corner of the window - - y (number) y coordinate from the top left corner of the window - > Usage - | Snap.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"}); - \*/ - Snap.getElementByPoint = function (x, y) { - var paper = this, - svg = paper.canvas, - target = glob.doc.elementFromPoint(x, y); - if (glob.win.opera && target.tagName == "svg") { - var so = getOffset(target), - sr = target.createSVGRect(); - sr.x = x - so.x; - sr.y = y - so.y; - sr.width = sr.height = 1; - var hits = target.getIntersectionList(sr, null); - if (hits.length) { - target = hits[hits.length - 1]; - } - } - if (!target) { - return null; - } - return wrap(target); - }; - /*\ - * Snap.plugin - [ method ] - ** - * Let you write plugins. You pass in a function with five arguments, like this: - | Snap.plugin(function (Snap, Element, Paper, global, Fragment) { - | Snap.newmethod = function () {}; - | Element.prototype.newmethod = function () {}; - | Paper.prototype.newmethod = function () {}; - | }); - * Inside the function you have access to all main objects (and their - * prototypes). This allow you to extend anything you want. - ** - - f (function) your plugin body - \*/ - Snap.plugin = function (f) { - f(Snap, Element, Paper, glob, Fragment); - }; - glob.win.Snap = Snap; - return Snap; - }(window || this)); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob, Fragment) { - var elproto = Element.prototype, - is = Snap.is, - Str = String, - unit2px = Snap._unit2px, - $ = Snap._.$, - make = Snap._.make, - getSomeDefs = Snap._.getSomeDefs, - has = "hasOwnProperty", - wrap = Snap._.wrap; - /*\ - * Element.getBBox - [ method ] - ** - * Returns the bounding box descriptor for the given element - ** - = (object) bounding box descriptor: - o { - o cx: (number) x of the center, - o cy: (number) x of the center, - o h: (number) height, - o height: (number) height, - o path: (string) path command for the box, - o r0: (number) radius of a circle that fully encloses the box, - o r1: (number) radius of the smallest circle that can be enclosed, - o r2: (number) radius of the largest circle that can be enclosed, - o vb: (string) box as a viewbox command, - o w: (number) width, - o width: (number) width, - o x2: (number) x of the right side, - o x: (number) x of the left side, - o y2: (number) y of the bottom edge, - o y: (number) y of the top edge - o } - \*/ - elproto.getBBox = function (isWithoutTransform) { - if (!Snap.Matrix || !Snap.path) { - return this.node.getBBox(); - } - var el = this, - m = new Snap.Matrix; - if (el.removed) { - return Snap._.box(); - } - while (el.type == "use") { - if (!isWithoutTransform) { - m = m.add(el.transform().localMatrix.translate(el.attr("x") || 0, el.attr("y") || 0)); - } - if (el.original) { - el = el.original; - } else { - var href = el.attr("xlink:href"); - el = el.original = el.node.ownerDocument.getElementById(href.substring(href.indexOf("#") + 1)); - } - } - var _ = el._, - pathfinder = Snap.path.get[el.type] || Snap.path.get.deflt; - try { - if (isWithoutTransform) { - _.bboxwt = pathfinder ? Snap.path.getBBox(el.realPath = pathfinder(el)) : Snap._.box(el.node.getBBox()); - return Snap._.box(_.bboxwt); - } else { - el.realPath = pathfinder(el); - el.matrix = el.transform().localMatrix; - _.bbox = Snap.path.getBBox(Snap.path.map(el.realPath, m.add(el.matrix))); - return Snap._.box(_.bbox); - } - } catch (e) { - // Firefox doesn’t give you bbox of hidden element - return Snap._.box(); - } - }; - var propString = function () { - return this.string; - }; - function extractTransform(el, tstr) { - if (tstr == null) { - var doReturn = true; - if (el.type == "linearGradient" || el.type == "radialGradient") { - tstr = el.node.getAttribute("gradientTransform"); - } else if (el.type == "pattern") { - tstr = el.node.getAttribute("patternTransform"); - } else { - tstr = el.node.getAttribute("transform"); - } - if (!tstr) { - return new Snap.Matrix; - } - tstr = Snap._.svgTransform2string(tstr); - } else { - if (!Snap._.rgTransform.test(tstr)) { - tstr = Snap._.svgTransform2string(tstr); - } else { - tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E); - } - if (is(tstr, "array")) { - tstr = Snap.path ? Snap.path.toString.call(tstr) : Str(tstr); - } - el._.transform = tstr; - } - var m = Snap._.transform2matrix(tstr, el.getBBox(1)); - if (doReturn) { - return m; - } else { - el.matrix = m; - } - } - /*\ - * Element.transform - [ method ] - ** - * Gets or sets transformation of the element - ** - - tstr (string) transform string in Snap or SVG format - = (Element) the current element - * or - = (object) transformation descriptor: - o { - o string (string) transform string, - o globalMatrix (Matrix) matrix of all transformations applied to element or its parents, - o localMatrix (Matrix) matrix of transformations applied only to the element, - o diffMatrix (Matrix) matrix of difference between global and local transformations, - o global (string) global transformation as string, - o local (string) local transformation as string, - o toString (function) returns `string` property - o } - \*/ - elproto.transform = function (tstr) { - var _ = this._; - if (tstr == null) { - var papa = this, - global = new Snap.Matrix(this.node.getCTM()), - local = extractTransform(this), - ms = [local], - m = new Snap.Matrix, - i, - localString = local.toTransformString(), - string = Str(local) == Str(this.matrix) ? - Str(_.transform) : localString; - while (papa.type != "svg" && (papa = papa.parent())) { - ms.push(extractTransform(papa)); - } - i = ms.length; - while (i--) { - m.add(ms[i]); - } - return { - string: string, - globalMatrix: global, - totalMatrix: m, - localMatrix: local, - diffMatrix: global.clone().add(local.invert()), - global: global.toTransformString(), - total: m.toTransformString(), - local: localString, - toString: propString - }; - } - if (tstr instanceof Snap.Matrix) { - this.matrix = tstr; - this._.transform = tstr.toTransformString(); - } else { - extractTransform(this, tstr); - } - - if (this.node) { - if (this.type == "linearGradient" || this.type == "radialGradient") { - $(this.node, {gradientTransform: this.matrix}); - } else if (this.type == "pattern") { - $(this.node, {patternTransform: this.matrix}); - } else { - $(this.node, {transform: this.matrix}); - } - } - - return this; - }; - /*\ - * Element.parent - [ method ] - ** - * Returns the element's parent - ** - = (Element) the parent element - \*/ - elproto.parent = function () { - return wrap(this.node.parentNode); - }; - /*\ - * Element.append - [ method ] - ** - * Appends the given element to current one - ** - - el (Element|Set) element to append - = (Element) the parent element - \*/ - /*\ - * Element.add - [ method ] - ** - * See @Element.append - \*/ - elproto.append = elproto.add = function (el) { - if (el) { - if (el.type == "set") { - var it = this; - el.forEach(function (el) { - it.add(el); - }); - return this; - } - el = wrap(el); - this.node.appendChild(el.node); - el.paper = this.paper; - } - return this; - }; - /*\ - * Element.appendTo - [ method ] - ** - * Appends the current element to the given one - ** - - el (Element) parent element to append to - = (Element) the child element - \*/ - elproto.appendTo = function (el) { - if (el) { - el = wrap(el); - el.append(this); - } - return this; - }; - /*\ - * Element.prepend - [ method ] - ** - * Prepends the given element to the current one - ** - - el (Element) element to prepend - = (Element) the parent element - \*/ - elproto.prepend = function (el) { - if (el) { - if (el.type == "set") { - var it = this, - first; - el.forEach(function (el) { - if (first) { - first.after(el); - } else { - it.prepend(el); - } - first = el; - }); - return this; - } - el = wrap(el); - var parent = el.parent(); - this.node.insertBefore(el.node, this.node.firstChild); - this.add && this.add(); - el.paper = this.paper; - this.parent() && this.parent().add(); - parent && parent.add(); - } - return this; - }; - /*\ - * Element.prependTo - [ method ] - ** - * Prepends the current element to the given one - ** - - el (Element) parent element to prepend to - = (Element) the child element - \*/ - elproto.prependTo = function (el) { - el = wrap(el); - el.prepend(this); - return this; - }; - /*\ - * Element.before - [ method ] - ** - * Inserts given element before the current one - ** - - el (Element) element to insert - = (Element) the parent element - \*/ - elproto.before = function (el) { - if (el.type == "set") { - var it = this; - el.forEach(function (el) { - var parent = el.parent(); - it.node.parentNode.insertBefore(el.node, it.node); - parent && parent.add(); - }); - this.parent().add(); - return this; - } - el = wrap(el); - var parent = el.parent(); - this.node.parentNode.insertBefore(el.node, this.node); - this.parent() && this.parent().add(); - parent && parent.add(); - el.paper = this.paper; - return this; - }; - /*\ - * Element.after - [ method ] - ** - * Inserts given element after the current one - ** - - el (Element) element to insert - = (Element) the parent element - \*/ - elproto.after = function (el) { - el = wrap(el); - var parent = el.parent(); - if (this.node.nextSibling) { - this.node.parentNode.insertBefore(el.node, this.node.nextSibling); - } else { - this.node.parentNode.appendChild(el.node); - } - this.parent() && this.parent().add(); - parent && parent.add(); - el.paper = this.paper; - return this; - }; - /*\ - * Element.insertBefore - [ method ] - ** - * Inserts the element after the given one - ** - - el (Element) element next to whom insert to - = (Element) the parent element - \*/ - elproto.insertBefore = function (el) { - el = wrap(el); - var parent = this.parent(); - el.node.parentNode.insertBefore(this.node, el.node); - this.paper = el.paper; - parent && parent.add(); - el.parent() && el.parent().add(); - return this; - }; - /*\ - * Element.insertAfter - [ method ] - ** - * Inserts the element after the given one - ** - - el (Element) element next to whom insert to - = (Element) the parent element - \*/ - elproto.insertAfter = function (el) { - el = wrap(el); - var parent = this.parent(); - el.node.parentNode.insertBefore(this.node, el.node.nextSibling); - this.paper = el.paper; - parent && parent.add(); - el.parent() && el.parent().add(); - return this; - }; - /*\ - * Element.remove - [ method ] - ** - * Removes element from the DOM - = (Element) the detached element - \*/ - elproto.remove = function () { - var parent = this.parent(); - this.node.parentNode && this.node.parentNode.removeChild(this.node); - delete this.paper; - this.removed = true; - parent && parent.add(); - return this; - }; - /*\ - * Element.select - [ method ] - ** - * Gathers the nested @Element matching the given set of CSS selectors - ** - - query (string) CSS selector - = (Element) result of query selection - \*/ - elproto.select = function (query) { - query = Str(query).replace(/([^\\]):/g, "$1\\:"); - return wrap(this.node.querySelector(query)); - }; - /*\ - * Element.selectAll - [ method ] - ** - * Gathers nested @Element objects matching the given set of CSS selectors - ** - - query (string) CSS selector - = (Set|array) result of query selection - \*/ - elproto.selectAll = function (query) { - var nodelist = this.node.querySelectorAll(query), - set = (Snap.set || Array)(); - for (var i = 0; i < nodelist.length; i++) { - set.push(wrap(nodelist[i])); - } - return set; - }; - /*\ - * Element.asPX - [ method ] - ** - * Returns given attribute of the element as a `px` value (not %, em, etc.) - ** - - attr (string) attribute name - - value (string) #optional attribute value - = (Element) result of query selection - \*/ - elproto.asPX = function (attr, value) { - if (value == null) { - value = this.attr(attr); - } - return +unit2px(this, attr, value); - }; - // SIERRA Element.use(): I suggest adding a note about how to access the original element the returned instantiates. It's a part of SVG with which ordinary web developers may be least familiar. - /*\ - * Element.use - [ method ] - ** - * Creates a `` element linked to the current element - ** - = (Element) the `` element - \*/ - elproto.use = function () { - var use, - id = this.node.id; - if (!id) { - id = this.id; - $(this.node, { - id: id - }); - } - if (this.type == "linearGradient" || this.type == "radialGradient" || - this.type == "pattern") { - use = make(this.type, this.node.parentNode); - } else { - use = make("use", this.node.parentNode); - } - $(use.node, { - "xlink:href": "#" + id - }); - use.original = this; - return use; - }; - function fixids(el) { - var els = el.selectAll("*"), - it, - url = /^\s*url\(("|'|)(.*)\1\)\s*$/, - ids = [], - uses = {}; - function urltest(it, name) { - var val = $(it.node, name); - val = val && val.match(url); - val = val && val[2]; - if (val && val.charAt() == "#") { - val = val.substring(1); - } else { - return; - } - if (val) { - uses[val] = (uses[val] || []).concat(function (id) { - var attr = {}; - attr[name] = URL(id); - $(it.node, attr); - }); - } - } - function linktest(it) { - var val = $(it.node, "xlink:href"); - if (val && val.charAt() == "#") { - val = val.substring(1); - } else { - return; - } - if (val) { - uses[val] = (uses[val] || []).concat(function (id) { - it.attr("xlink:href", "#" + id); - }); - } - } - for (var i = 0, ii = els.length; i < ii; i++) { - it = els[i]; - urltest(it, "fill"); - urltest(it, "stroke"); - urltest(it, "filter"); - urltest(it, "mask"); - urltest(it, "clip-path"); - linktest(it); - var oldid = $(it.node, "id"); - if (oldid) { - $(it.node, {id: it.id}); - ids.push({ - old: oldid, - id: it.id - }); - } - } - for (i = 0, ii = ids.length; i < ii; i++) { - var fs = uses[ids[i].old]; - if (fs) { - for (var j = 0, jj = fs.length; j < jj; j++) { - fs[j](ids[i].id); - } - } - } - } - /*\ - * Element.clone - [ method ] - ** - * Creates a clone of the element and inserts it after the element - ** - = (Element) the clone - \*/ - elproto.clone = function () { - var clone = wrap(this.node.cloneNode(true)); - if ($(clone.node, "id")) { - $(clone.node, {id: clone.id}); - } - fixids(clone); - clone.insertAfter(this); - return clone; - }; - /*\ - * Element.toDefs - [ method ] - ** - * Moves element to the shared `` area - ** - = (Element) the element - \*/ - elproto.toDefs = function () { - var defs = getSomeDefs(this); - defs.appendChild(this.node); - return this; - }; - /*\ - * Element.toPattern - [ method ] - ** - * Creates a `` element from the current element - ** - * To create a pattern you have to specify the pattern rect: - - x (string|number) - - y (string|number) - - width (string|number) - - height (string|number) - = (Element) the `` element - * You can use pattern later on as an argument for `fill` attribute: - | var p = paper.path("M10-5-10,15M15,0,0,15M0-5-20,15").attr({ - | fill: "none", - | stroke: "#bada55", - | strokeWidth: 5 - | }).pattern(0, 0, 10, 10), - | c = paper.circle(200, 200, 100); - | c.attr({ - | fill: p - | }); - \*/ - elproto.pattern = elproto.toPattern = function (x, y, width, height) { - var p = make("pattern", getSomeDefs(this)); - if (x == null) { - x = this.getBBox(); - } - if (is(x, "object") && "x" in x) { - y = x.y; - width = x.width; - height = x.height; - x = x.x; - } - $(p.node, { - x: x, - y: y, - width: width, - height: height, - patternUnits: "userSpaceOnUse", - id: p.id, - viewBox: [x, y, width, height].join(" ") - }); - p.node.appendChild(this.node); - return p; - }; - // SIERRA Element.marker(): clarify what a reference point is. E.g., helps you offset the object from its edge such as when centering it over a path. - // SIERRA Element.marker(): I suggest the method should accept default reference point values. Perhaps centered with (refX = width/2) and (refY = height/2)? Also, couldn't it assume the element's current _width_ and _height_? And please specify what _x_ and _y_ mean: offsets? If so, from where? Couldn't they also be assigned default values? - /*\ - * Element.marker - [ method ] - ** - * Creates a `` element from the current element - ** - * To create a marker you have to specify the bounding rect and reference point: - - x (number) - - y (number) - - width (number) - - height (number) - - refX (number) - - refY (number) - = (Element) the `` element - * You can specify the marker later as an argument for `marker-start`, `marker-end`, `marker-mid`, and `marker` attributes. The `marker` attribute places the marker at every point along the path, and `marker-mid` places them at every point except the start and end. - \*/ - // TODO add usage for markers - elproto.marker = function (x, y, width, height, refX, refY) { - var p = make("marker", getSomeDefs(this)); - if (x == null) { - x = this.getBBox(); - } - if (is(x, "object") && "x" in x) { - y = x.y; - width = x.width; - height = x.height; - refX = x.refX || x.cx; - refY = x.refY || x.cy; - x = x.x; - } - $(p.node, { - viewBox: [x, y, width, height].join(" "), - markerWidth: width, - markerHeight: height, - orient: "auto", - refX: refX || 0, - refY: refY || 0, - id: p.id - }); - p.node.appendChild(this.node); - return p; - }; - // animation - function slice(from, to, f) { - return function (arr) { - var res = arr.slice(from, to); - if (res.length == 1) { - res = res[0]; - } - return f ? f(res) : res; - }; - } - var Animation = function (attr, ms, easing, callback) { - if (typeof easing == "function" && !easing.length) { - callback = easing; - easing = mina.linear; - } - this.attr = attr; - this.dur = ms; - easing && (this.easing = easing); - callback && (this.callback = callback); - }; - Snap._.Animation = Animation; - /*\ - * Snap.animation - [ method ] - ** - * Creates an animation object - ** - - attr (object) attributes of final destination - - duration (number) duration of the animation, in milliseconds - - easing (function) #optional one of easing functions of @mina or custom one - - callback (function) #optional callback function that fires when animation ends - = (object) animation object - \*/ - Snap.animation = function (attr, ms, easing, callback) { - return new Animation(attr, ms, easing, callback); - }; - /*\ - * Element.inAnim - [ method ] - ** - * Returns a set of animations that may be able to manipulate the current element - ** - = (object) in format: - o { - o anim (object) animation object, - o mina (object) @mina object, - o curStatus (number) 0..1 — status of the animation: 0 — just started, 1 — just finished, - o status (function) gets or sets the status of the animation, - o stop (function) stops the animation - o } - \*/ - elproto.inAnim = function () { - var el = this, - res = []; - for (var id in el.anims) if (el.anims[has](id)) { - (function (a) { - res.push({ - anim: new Animation(a._attrs, a.dur, a.easing, a._callback), - mina: a, - curStatus: a.status(), - status: function (val) { - return a.status(val); - }, - stop: function () { - a.stop(); - } - }); - }(el.anims[id])); - } - return res; - }; - /*\ - * Snap.animate - [ method ] - ** - * Runs generic animation of one number into another with a caring function - ** - - from (number|array) number or array of numbers - - to (number|array) number or array of numbers - - setter (function) caring function that accepts one number argument - - duration (number) duration, in milliseconds - - easing (function) #optional easing function from @mina or custom - - callback (function) #optional callback function to execute when animation ends - = (object) animation object in @mina format - o { - o id (string) animation id, consider it read-only, - o duration (function) gets or sets the duration of the animation, - o easing (function) easing, - o speed (function) gets or sets the speed of the animation, - o status (function) gets or sets the status of the animation, - o stop (function) stops the animation - o } - | var rect = Snap().rect(0, 0, 10, 10); - | Snap.animate(0, 10, function (val) { - | rect.attr({ - | x: val - | }); - | }, 1000); - | // in given context is equivalent to - | rect.animate({x: 10}, 1000); - \*/ - Snap.animate = function (from, to, setter, ms, easing, callback) { - if (typeof easing == "function" && !easing.length) { - callback = easing; - easing = mina.linear; - } - var now = mina.time(), - anim = mina(from, to, now, now + ms, mina.time, setter, easing); - callback && eve.once("mina.finish." + anim.id, callback); - return anim; - }; - /*\ - * Element.stop - [ method ] - ** - * Stops all the animations for the current element - ** - = (Element) the current element - \*/ - elproto.stop = function () { - var anims = this.inAnim(); - for (var i = 0, ii = anims.length; i < ii; i++) { - anims[i].stop(); - } - return this; - }; - /*\ - * Element.animate - [ method ] - ** - * Animates the given attributes of the element - ** - - attrs (object) key-value pairs of destination attributes - - duration (number) duration of the animation in milliseconds - - easing (function) #optional easing function from @mina or custom - - callback (function) #optional callback function that executes when the animation ends - = (Element) the current element - \*/ - elproto.animate = function (attrs, ms, easing, callback) { - if (typeof easing == "function" && !easing.length) { - callback = easing; - easing = mina.linear; - } - if (attrs instanceof Animation) { - callback = attrs.callback; - easing = attrs.easing; - ms = easing.dur; - attrs = attrs.attr; - } - var fkeys = [], tkeys = [], keys = {}, from, to, f, eq, - el = this; - for (var key in attrs) if (attrs[has](key)) { - if (el.equal) { - eq = el.equal(key, Str(attrs[key])); - from = eq.from; - to = eq.to; - f = eq.f; - } else { - from = +el.attr(key); - to = +attrs[key]; - } - var len = is(from, "array") ? from.length : 1; - keys[key] = slice(fkeys.length, fkeys.length + len, f); - fkeys = fkeys.concat(from); - tkeys = tkeys.concat(to); - } - var now = mina.time(), - anim = mina(fkeys, tkeys, now, now + ms, mina.time, function (val) { - var attr = {}; - for (var key in keys) if (keys[has](key)) { - attr[key] = keys[key](val); - } - el.attr(attr); - }, easing); - el.anims[anim.id] = anim; - anim._attrs = attrs; - anim._callback = callback; - eve("snap.animcreated." + el.id, anim); - eve.once("mina.finish." + anim.id, function () { - delete el.anims[anim.id]; - callback && callback.call(el); - }); - eve.once("mina.stop." + anim.id, function () { - delete el.anims[anim.id]; - }); - return el; - }; - var eldata = {}; - /*\ - * Element.data - [ method ] - ** - * Adds or retrieves given value associated with given key. (Don’t confuse - * with `data-` attributes) - * - * See also @Element.removeData - - key (string) key to store data - - value (any) #optional value to store - = (object) @Element - * or, if value is not specified: - = (any) value - > Usage - | for (var i = 0, i < 5, i++) { - | paper.circle(10 + 15 * i, 10, 10) - | .attr({fill: "#000"}) - | .data("i", i) - | .click(function () { - | alert(this.data("i")); - | }); - | } - \*/ - elproto.data = function (key, value) { - var data = eldata[this.id] = eldata[this.id] || {}; - if (arguments.length == 0){ - eve("snap.data.get." + this.id, this, data, null); - return data; - } - if (arguments.length == 1) { - if (Snap.is(key, "object")) { - for (var i in key) if (key[has](i)) { - this.data(i, key[i]); - } - return this; - } - eve("snap.data.get." + this.id, this, data[key], key); - return data[key]; - } - data[key] = value; - eve("snap.data.set." + this.id, this, value, key); - return this; - }; - /*\ - * Element.removeData - [ method ] - ** - * Removes value associated with an element by given key. - * If key is not provided, removes all the data of the element. - - key (string) #optional key - = (object) @Element - \*/ - elproto.removeData = function (key) { - if (key == null) { - eldata[this.id] = {}; - } else { - eldata[this.id] && delete eldata[this.id][key]; - } - return this; - }; - /*\ - * Element.outerSVG - [ method ] - ** - * Returns SVG code for the element, equivalent to HTML's `outerHTML`. - * - * See also @Element.innerSVG - = (string) SVG code for the element - \*/ - /*\ - * Element.toString - [ method ] - ** - * See @Element.outerSVG - \*/ - elproto.outerSVG = elproto.toString = toString(1); - /*\ - * Element.innerSVG - [ method ] - ** - * Returns SVG code for the element's contents, equivalent to HTML's `innerHTML` - = (string) SVG code for the element - \*/ - elproto.innerSVG = toString(); - function toString(type) { - return function () { - var res = type ? "<" + this.type : "", - attr = this.node.attributes, - chld = this.node.childNodes; - if (type) { - for (var i = 0, ii = attr.length; i < ii; i++) { - res += " " + attr[i].name + '="' + - attr[i].value.replace(/"/g, '\\"') + '"'; - } - } - if (chld.length) { - type && (res += ">"); - for (i = 0, ii = chld.length; i < ii; i++) { - if (chld[i].nodeType == 3) { - res += chld[i].nodeValue; - } else if (chld[i].nodeType == 1) { - res += wrap(chld[i]).toString(); - } - } - type && (res += ""); - } else { - type && (res += "/>"); - } - return res; - }; - } - elproto.toDataURL = function () { - if (window && window.btoa) { - var bb = this.getBBox(), - svg = Snap.format('{contents}', { - x: +bb.x.toFixed(3), - y: +bb.y.toFixed(3), - width: +bb.width.toFixed(3), - height: +bb.height.toFixed(3), - contents: this.outerSVG() - }); - return "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svg))); - } - }; - /*\ - * Fragment.select - [ method ] - ** - * See @Element.select - \*/ - Fragment.prototype.select = elproto.select; - /*\ - * Fragment.selectAll - [ method ] - ** - * See @Element.selectAll - \*/ - Fragment.prototype.selectAll = elproto.selectAll; - }); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob, Fragment) { - var objectToString = Object.prototype.toString, - Str = String, - math = Math, - E = ""; - function Matrix(a, b, c, d, e, f) { - if (b == null && objectToString.call(a) == "[object SVGMatrix]") { - this.a = a.a; - this.b = a.b; - this.c = a.c; - this.d = a.d; - this.e = a.e; - this.f = a.f; - return; - } - if (a != null) { - this.a = +a; - this.b = +b; - this.c = +c; - this.d = +d; - this.e = +e; - this.f = +f; - } else { - this.a = 1; - this.b = 0; - this.c = 0; - this.d = 1; - this.e = 0; - this.f = 0; - } - } - (function (matrixproto) { - /*\ - * Matrix.add - [ method ] - ** - * Adds the given matrix to existing one - - a (number) - - b (number) - - c (number) - - d (number) - - e (number) - - f (number) - * or - - matrix (object) @Matrix - \*/ - matrixproto.add = function (a, b, c, d, e, f) { - var out = [[], [], []], - m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]], - matrix = [[a, c, e], [b, d, f], [0, 0, 1]], - x, y, z, res; - - if (a && a instanceof Matrix) { - matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]]; - } - - for (x = 0; x < 3; x++) { - for (y = 0; y < 3; y++) { - res = 0; - for (z = 0; z < 3; z++) { - res += m[x][z] * matrix[z][y]; - } - out[x][y] = res; - } - } - this.a = out[0][0]; - this.b = out[1][0]; - this.c = out[0][1]; - this.d = out[1][1]; - this.e = out[0][2]; - this.f = out[1][2]; - return this; - }; - /*\ - * Matrix.invert - [ method ] - ** - * Returns an inverted version of the matrix - = (object) @Matrix - \*/ - matrixproto.invert = function () { - var me = this, - x = me.a * me.d - me.b * me.c; - return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x); - }; - /*\ - * Matrix.clone - [ method ] - ** - * Returns a copy of the matrix - = (object) @Matrix - \*/ - matrixproto.clone = function () { - return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f); - }; - /*\ - * Matrix.translate - [ method ] - ** - * Translate the matrix - - x (number) horizontal offset distance - - y (number) vertical offset distance - \*/ - matrixproto.translate = function (x, y) { - return this.add(1, 0, 0, 1, x, y); - }; - /*\ - * Matrix.scale - [ method ] - ** - * Scales the matrix - - x (number) amount to be scaled, with `1` resulting in no change - - y (number) #optional amount to scale along the vertical axis. (Otherwise `x` applies to both axes.) - - cx (number) #optional horizontal origin point from which to scale - - cy (number) #optional vertical origin point from which to scale - * Default cx, cy is the middle point of the element. - \*/ - matrixproto.scale = function (x, y, cx, cy) { - y == null && (y = x); - (cx || cy) && this.add(1, 0, 0, 1, cx, cy); - this.add(x, 0, 0, y, 0, 0); - (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy); - return this; - }; - /*\ - * Matrix.rotate - [ method ] - ** - * Rotates the matrix - - a (number) angle of rotation, in degrees - - x (number) horizontal origin point from which to rotate - - y (number) vertical origin point from which to rotate - \*/ - matrixproto.rotate = function (a, x, y) { - a = Snap.rad(a); - x = x || 0; - y = y || 0; - var cos = +math.cos(a).toFixed(9), - sin = +math.sin(a).toFixed(9); - this.add(cos, sin, -sin, cos, x, y); - return this.add(1, 0, 0, 1, -x, -y); - }; - /*\ - * Matrix.x - [ method ] - ** - * Returns x coordinate for given point after transformation described by the matrix. See also @Matrix.y - - x (number) - - y (number) - = (number) x - \*/ - matrixproto.x = function (x, y) { - return x * this.a + y * this.c + this.e; - }; - /*\ - * Matrix.y - [ method ] - ** - * Returns y coordinate for given point after transformation described by the matrix. See also @Matrix.x - - x (number) - - y (number) - = (number) y - \*/ - matrixproto.y = function (x, y) { - return x * this.b + y * this.d + this.f; - }; - matrixproto.get = function (i) { - return +this[Str.fromCharCode(97 + i)].toFixed(4); - }; - matrixproto.toString = function () { - return "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")"; - }; - matrixproto.offset = function () { - return [this.e.toFixed(4), this.f.toFixed(4)]; - }; - function norm(a) { - return a[0] * a[0] + a[1] * a[1]; - } - function normalize(a) { - var mag = math.sqrt(norm(a)); - a[0] && (a[0] /= mag); - a[1] && (a[1] /= mag); - } - /*\ - * Matrix.determinant - [ method ] - ** - * Finds determinant of the given matrix. - = (number) determinant - \*/ - matrixproto.determinant = function () { - return this.a * this.d - this.b * this.c; - }; - /*\ - * Matrix.split - [ method ] - ** - * Splits matrix into primitive transformations - = (object) in format: - o dx (number) translation by x - o dy (number) translation by y - o scalex (number) scale by x - o scaley (number) scale by y - o shear (number) shear - o rotate (number) rotation in deg - o isSimple (boolean) could it be represented via simple transformations - \*/ - matrixproto.split = function () { - var out = {}; - // translation - out.dx = this.e; - out.dy = this.f; - - // scale and shear - var row = [[this.a, this.c], [this.b, this.d]]; - out.scalex = math.sqrt(norm(row[0])); - normalize(row[0]); - - out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1]; - row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear]; - - out.scaley = math.sqrt(norm(row[1])); - normalize(row[1]); - out.shear /= out.scaley; - - if (this.determinant() < 0) { - out.scalex = -out.scalex; - } - - // rotation - var sin = -row[0][1], - cos = row[1][1]; - if (cos < 0) { - out.rotate = Snap.deg(math.acos(cos)); - if (sin < 0) { - out.rotate = 360 - out.rotate; - } - } else { - out.rotate = Snap.deg(math.asin(sin)); - } - - out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate); - out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate; - out.noRotation = !+out.shear.toFixed(9) && !out.rotate; - return out; - }; - /*\ - * Matrix.toTransformString - [ method ] - ** - * Returns transform string that represents given matrix - = (string) transform string - \*/ - matrixproto.toTransformString = function (shorter) { - var s = shorter || this.split(); - if (!+s.shear.toFixed(9)) { - s.scalex = +s.scalex.toFixed(4); - s.scaley = +s.scaley.toFixed(4); - s.rotate = +s.rotate.toFixed(4); - return (s.dx || s.dy ? "t" + [+s.dx.toFixed(4), +s.dy.toFixed(4)] : E) + - (s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) + - (s.rotate ? "r" + [+s.rotate.toFixed(4), 0, 0] : E); - } else { - return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)]; - } - }; - })(Matrix.prototype); - /*\ - * Snap.Matrix - [ method ] - ** - * Matrix constructor, extend on your own risk. - * To create matrices use @Snap.matrix. - \*/ - Snap.Matrix = Matrix; - /*\ - * Snap.matrix - [ method ] - ** - * Utility method - ** - * Returns a matrix based on the given parameters - - a (number) - - b (number) - - c (number) - - d (number) - - e (number) - - f (number) - * or - - svgMatrix (SVGMatrix) - = (object) @Matrix - \*/ - Snap.matrix = function (a, b, c, d, e, f) { - return new Matrix(a, b, c, d, e, f); - }; - }); - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob, Fragment) { - var has = "hasOwnProperty", - make = Snap._.make, - wrap = Snap._.wrap, - is = Snap.is, - getSomeDefs = Snap._.getSomeDefs, - reURLValue = /^url\(#?([^)]+)\)$/, - $ = Snap._.$, - URL = Snap.url, - Str = String, - separator = Snap._.separator, - E = ""; - // Attributes event handlers - eve.on("snap.util.attr.mask", function (value) { - if (value instanceof Element || value instanceof Fragment) { - eve.stop(); - if (value instanceof Fragment && value.node.childNodes.length == 1) { - value = value.node.firstChild; - getSomeDefs(this).appendChild(value); - value = wrap(value); - } - if (value.type == "mask") { - var mask = value; - } else { - mask = make("mask", getSomeDefs(this)); - mask.node.appendChild(value.node); - } - !mask.node.id && $(mask.node, { - id: mask.id - }); - $(this.node, { - mask: URL(mask.id) - }); - } - }); - (function (clipIt) { - eve.on("snap.util.attr.clip", clipIt); - eve.on("snap.util.attr.clip-path", clipIt); - eve.on("snap.util.attr.clipPath", clipIt); - }(function (value) { - if (value instanceof Element || value instanceof Fragment) { - eve.stop(); - if (value.type == "clipPath") { - var clip = value; - } else { - clip = make("clipPath", getSomeDefs(this)); - clip.node.appendChild(value.node); - !clip.node.id && $(clip.node, { - id: clip.id - }); - } - $(this.node, { - "clip-path": URL(clip.node.id || clip.id) - }); - } - })); - function fillStroke(name) { - return function (value) { - eve.stop(); - if (value instanceof Fragment && value.node.childNodes.length == 1 && - (value.node.firstChild.tagName == "radialGradient" || - value.node.firstChild.tagName == "linearGradient" || - value.node.firstChild.tagName == "pattern")) { - value = value.node.firstChild; - getSomeDefs(this).appendChild(value); - value = wrap(value); - } - if (value instanceof Element) { - if (value.type == "radialGradient" || value.type == "linearGradient" - || value.type == "pattern") { - if (!value.node.id) { - $(value.node, { - id: value.id - }); - } - var fill = URL(value.node.id); - } else { - fill = value.attr(name); - } - } else { - fill = Snap.color(value); - if (fill.error) { - var grad = Snap(getSomeDefs(this).ownerSVGElement).gradient(value); - if (grad) { - if (!grad.node.id) { - $(grad.node, { - id: grad.id - }); - } - fill = URL(grad.node.id); - } else { - fill = value; - } - } else { - fill = Str(fill); - } - } - var attrs = {}; - attrs[name] = fill; - $(this.node, attrs); - this.node.style[name] = E; - }; - } - eve.on("snap.util.attr.fill", fillStroke("fill")); - eve.on("snap.util.attr.stroke", fillStroke("stroke")); - var gradrg = /^([lr])(?:\(([^)]*)\))?(.*)$/i; - eve.on("snap.util.grad.parse", function parseGrad(string) { - string = Str(string); - var tokens = string.match(gradrg); - if (!tokens) { - return null; - } - var type = tokens[1], - params = tokens[2], - stops = tokens[3]; - params = params.split(/\s*,\s*/).map(function (el) { - return +el == el ? +el : el; - }); - if (params.length == 1 && params[0] == 0) { - params = []; - } - stops = stops.split("-"); - stops = stops.map(function (el) { - el = el.split(":"); - var out = { - color: el[0] - }; - if (el[1]) { - out.offset = parseFloat(el[1]); - } - return out; - }); - return { - type: type, - params: params, - stops: stops - }; - }); - - eve.on("snap.util.attr.d", function (value) { - eve.stop(); - if (is(value, "array") && is(value[0], "array")) { - value = Snap.path.toString.call(value); - } - value = Str(value); - if (value.match(/[ruo]/i)) { - value = Snap.path.toAbsolute(value); - } - $(this.node, {d: value}); - })(-1); - eve.on("snap.util.attr.#text", function (value) { - eve.stop(); - value = Str(value); - var txt = glob.doc.createTextNode(value); - while (this.node.firstChild) { - this.node.removeChild(this.node.firstChild); - } - this.node.appendChild(txt); - })(-1); - eve.on("snap.util.attr.path", function (value) { - eve.stop(); - this.attr({d: value}); - })(-1); - eve.on("snap.util.attr.class", function (value) { - eve.stop(); - this.node.className.baseVal = value; - })(-1); - eve.on("snap.util.attr.viewBox", function (value) { - var vb; - if (is(value, "object") && "x" in value) { - vb = [value.x, value.y, value.width, value.height].join(" "); - } else if (is(value, "array")) { - vb = value.join(" "); - } else { - vb = value; - } - $(this.node, { - viewBox: vb - }); - eve.stop(); - })(-1); - eve.on("snap.util.attr.transform", function (value) { - this.transform(value); - eve.stop(); - })(-1); - eve.on("snap.util.attr.r", function (value) { - if (this.type == "rect") { - eve.stop(); - $(this.node, { - rx: value, - ry: value - }); - } - })(-1); - eve.on("snap.util.attr.textpath", function (value) { - eve.stop(); - if (this.type == "text") { - var id, tp, node; - if (!value && this.textPath) { - tp = this.textPath; - while (tp.node.firstChild) { - this.node.appendChild(tp.node.firstChild); - } - tp.remove(); - delete this.textPath; - return; - } - if (is(value, "string")) { - var defs = getSomeDefs(this), - path = wrap(defs.parentNode).path(value); - defs.appendChild(path.node); - id = path.id; - path.attr({id: id}); - } else { - value = wrap(value); - if (value instanceof Element) { - id = value.attr("id"); - if (!id) { - id = value.id; - value.attr({id: id}); - } - } - } - if (id) { - tp = this.textPath; - node = this.node; - if (tp) { - tp.attr({"xlink:href": "#" + id}); - } else { - tp = $("textPath", { - "xlink:href": "#" + id - }); - while (node.firstChild) { - tp.appendChild(node.firstChild); - } - node.appendChild(tp); - this.textPath = wrap(tp); - } - } - } - })(-1); - eve.on("snap.util.attr.text", function (value) { - if (this.type == "text") { - var i = 0, - node = this.node, - tuner = function (chunk) { - var out = $("tspan"); - if (is(chunk, "array")) { - for (var i = 0; i < chunk.length; i++) { - out.appendChild(tuner(chunk[i])); - } - } else { - out.appendChild(glob.doc.createTextNode(chunk)); - } - out.normalize && out.normalize(); - return out; - }; - while (node.firstChild) { - node.removeChild(node.firstChild); - } - var tuned = tuner(value); - while (tuned.firstChild) { - node.appendChild(tuned.firstChild); - } - } - eve.stop(); - })(-1); - function setFontSize(value) { - eve.stop(); - if (value == +value) { - value += "px"; - } - this.node.style.fontSize = value; - } - eve.on("snap.util.attr.fontSize", setFontSize)(-1); - eve.on("snap.util.attr.font-size", setFontSize)(-1); - - - eve.on("snap.util.getattr.transform", function () { - eve.stop(); - return this.transform(); - })(-1); - eve.on("snap.util.getattr.textpath", function () { - eve.stop(); - return this.textPath; - })(-1); - // Markers - (function () { - function getter(end) { - return function () { - eve.stop(); - var style = glob.doc.defaultView.getComputedStyle(this.node, null).getPropertyValue("marker-" + end); - if (style == "none") { - return style; - } else { - return Snap(glob.doc.getElementById(style.match(reURLValue)[1])); - } - }; - } - function setter(end) { - return function (value) { - eve.stop(); - var name = "marker" + end.charAt(0).toUpperCase() + end.substring(1); - if (value == "" || !value) { - this.node.style[name] = "none"; - return; - } - if (value.type == "marker") { - var id = value.node.id; - if (!id) { - $(value.node, {id: value.id}); - } - this.node.style[name] = URL(id); - return; - } - }; - } - eve.on("snap.util.getattr.marker-end", getter("end"))(-1); - eve.on("snap.util.getattr.markerEnd", getter("end"))(-1); - eve.on("snap.util.getattr.marker-start", getter("start"))(-1); - eve.on("snap.util.getattr.markerStart", getter("start"))(-1); - eve.on("snap.util.getattr.marker-mid", getter("mid"))(-1); - eve.on("snap.util.getattr.markerMid", getter("mid"))(-1); - eve.on("snap.util.attr.marker-end", setter("end"))(-1); - eve.on("snap.util.attr.markerEnd", setter("end"))(-1); - eve.on("snap.util.attr.marker-start", setter("start"))(-1); - eve.on("snap.util.attr.markerStart", setter("start"))(-1); - eve.on("snap.util.attr.marker-mid", setter("mid"))(-1); - eve.on("snap.util.attr.markerMid", setter("mid"))(-1); - }()); - eve.on("snap.util.getattr.r", function () { - if (this.type == "rect" && $(this.node, "rx") == $(this.node, "ry")) { - eve.stop(); - return $(this.node, "rx"); - } - })(-1); - function textExtract(node) { - var out = []; - var children = node.childNodes; - for (var i = 0, ii = children.length; i < ii; i++) { - var chi = children[i]; - if (chi.nodeType == 3) { - out.push(chi.nodeValue); - } - if (chi.tagName == "tspan") { - if (chi.childNodes.length == 1 && chi.firstChild.nodeType == 3) { - out.push(chi.firstChild.nodeValue); - } else { - out.push(textExtract(chi)); - } - } - } - return out; - } - eve.on("snap.util.getattr.text", function () { - if (this.type == "text" || this.type == "tspan") { - eve.stop(); - var out = textExtract(this.node); - return out.length == 1 ? out[0] : out; - } - })(-1); - eve.on("snap.util.getattr.#text", function () { - return this.node.textContent; - })(-1); - eve.on("snap.util.getattr.viewBox", function () { - eve.stop(); - var vb = $(this.node, "viewBox"); - if (vb) { - vb = vb.split(separator); - return Snap._.box(+vb[0], +vb[1], +vb[2], +vb[3]); - } else { - return; - } - })(-1); - eve.on("snap.util.getattr.points", function () { - var p = $(this.node, "points"); - eve.stop(); - if (p) { - return p.split(separator); - } else { - return; - } - })(-1); - eve.on("snap.util.getattr.path", function () { - var p = $(this.node, "d"); - eve.stop(); - return p; - })(-1); - eve.on("snap.util.getattr.class", function () { - return this.node.className.baseVal; - })(-1); - function getFontSize() { - eve.stop(); - return this.node.style.fontSize; - } - eve.on("snap.util.getattr.fontSize", getFontSize)(-1); - eve.on("snap.util.getattr.font-size", getFontSize)(-1); - }); - - // Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob, Fragment) { - var rgNotSpace = /\S+/g, - rgBadSpace = /[\t\r\n\f]/g, - rgTrim = /(^\s+|\s+$)/g, - Str = String, - elproto = Element.prototype; - /*\ - * Element.addClass - [ method ] - ** - * Adds given class name or list of class names to the element. - - value (string) class name or space separated list of class names - ** - = (Element) original element. - \*/ - elproto.addClass = function (value) { - var classes = Str(value || "").match(rgNotSpace) || [], - elem = this.node, - className = elem.className.baseVal, - curClasses = className.match(rgNotSpace) || [], - j, - pos, - clazz, - finalValue; - - if (classes.length) { - j = 0; - while ((clazz = classes[j++])) { - pos = curClasses.indexOf(clazz); - if (!~pos) { - curClasses.push(clazz); - } - } - - finalValue = curClasses.join(" "); - if (className != finalValue) { - elem.className.baseVal = finalValue; - } - } - return this; - }; - /*\ - * Element.removeClass - [ method ] - ** - * Removes given class name or list of class names from the element. - - value (string) class name or space separated list of class names - ** - = (Element) original element. - \*/ - elproto.removeClass = function (value) { - var classes = Str(value || "").match(rgNotSpace) || [], - elem = this.node, - className = elem.className.baseVal, - curClasses = className.match(rgNotSpace) || [], - j, - pos, - clazz, - finalValue; - if (curClasses.length) { - j = 0; - while ((clazz = classes[j++])) { - pos = curClasses.indexOf(clazz); - if (~pos) { - curClasses.splice(pos, 1); - } - } - - finalValue = curClasses.join(" "); - if (className != finalValue) { - elem.className.baseVal = finalValue; - } - } - return this; - }; - /*\ - * Element.hasClass - [ method ] - ** - * Checks if the element has a given class name in the list of class names applied to it. - - value (string) class name - ** - = (boolean) `true` if the element has given class - \*/ - elproto.hasClass = function (value) { - var elem = this.node, - className = elem.className.baseVal, - curClasses = className.match(rgNotSpace) || []; - return !!~curClasses.indexOf(value); - }; - /*\ - * Element.toggleClass - [ method ] - ** - * Add or remove one or more classes from the element, depending on either - * the class’s presence or the value of the `flag` argument. - - value (string) class name or space separated list of class names - - flag (boolean) value to determine whether the class should be added or removed - ** - = (Element) original element. - \*/ - elproto.toggleClass = function (value, flag) { - if (flag != null) { - if (flag) { - return this.addClass(value); - } else { - return this.removeClass(value); - } - } - var classes = (value || "").match(rgNotSpace) || [], - elem = this.node, - className = elem.className.baseVal, - curClasses = className.match(rgNotSpace) || [], - j, - pos, - clazz, - finalValue; - j = 0; - while ((clazz = classes[j++])) { - pos = curClasses.indexOf(clazz); - if (~pos) { - curClasses.splice(pos, 1); - } else { - curClasses.push(clazz); - } - } - - finalValue = curClasses.join(" "); - if (className != finalValue) { - elem.className.baseVal = finalValue; - } - return this; - }; - }); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob, Fragment) { - var operators = { - "+": function (x, y) { - return x + y; - }, - "-": function (x, y) { - return x - y; - }, - "/": function (x, y) { - return x / y; - }, - "*": function (x, y) { - return x * y; - } - }, - Str = String, - reUnit = /[a-z]+$/i, - reAddon = /^\s*([+\-\/*])\s*=\s*([\d.eE+\-]+)\s*([^\d\s]+)?\s*$/; - function getNumber(val) { - return val; - } - function getUnit(unit) { - return function (val) { - return +val.toFixed(3) + unit; - }; - } - eve.on("snap.util.attr", function (val) { - var plus = Str(val).match(reAddon); - if (plus) { - var evnt = eve.nt(), - name = evnt.substring(evnt.lastIndexOf(".") + 1), - a = this.attr(name), - atr = {}; - eve.stop(); - var unit = plus[3] || "", - aUnit = a.match(reUnit), - op = operators[plus[1]]; - if (aUnit && aUnit == unit) { - val = op(parseFloat(a), +plus[2]); - } else { - a = this.asPX(name); - val = op(this.asPX(name), this.asPX(name, plus[2] + unit)); - } - if (isNaN(a) || isNaN(val)) { - return; - } - atr[name] = val; - this.attr(atr); - } - })(-10); - eve.on("snap.util.equal", function (name, b) { - var A, B, a = Str(this.attr(name) || ""), - el = this, - bplus = Str(b).match(reAddon); - if (bplus) { - eve.stop(); - var unit = bplus[3] || "", - aUnit = a.match(reUnit), - op = operators[bplus[1]]; - if (aUnit && aUnit == unit) { - return { - from: parseFloat(a), - to: op(parseFloat(a), +bplus[2]), - f: getUnit(aUnit) - }; - } else { - a = this.asPX(name); - return { - from: a, - to: op(a, this.asPX(name, bplus[2] + unit)), - f: getNumber - }; - } - } - })(-10); - }); - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob, Fragment) { - var proto = Paper.prototype, - is = Snap.is; - /*\ - * Paper.rect - [ method ] - * - * Draws a rectangle - ** - - x (number) x coordinate of the top left corner - - y (number) y coordinate of the top left corner - - width (number) width - - height (number) height - - rx (number) #optional horizontal radius for rounded corners, default is 0 - - ry (number) #optional vertical radius for rounded corners, default is rx or 0 - = (object) the `rect` element - ** - > Usage - | // regular rectangle - | var c = paper.rect(10, 10, 50, 50); - | // rectangle with rounded corners - | var c = paper.rect(40, 40, 50, 50, 10); - \*/ - proto.rect = function (x, y, w, h, rx, ry) { - var attr; - if (ry == null) { - ry = rx; - } - if (is(x, "object") && x == "[object Object]") { - attr = x; - } else if (x != null) { - attr = { - x: x, - y: y, - width: w, - height: h - }; - if (rx != null) { - attr.rx = rx; - attr.ry = ry; - } - } - return this.el("rect", attr); - }; - /*\ - * Paper.circle - [ method ] - ** - * Draws a circle - ** - - x (number) x coordinate of the centre - - y (number) y coordinate of the centre - - r (number) radius - = (object) the `circle` element - ** - > Usage - | var c = paper.circle(50, 50, 40); - \*/ - proto.circle = function (cx, cy, r) { - var attr; - if (is(cx, "object") && cx == "[object Object]") { - attr = cx; - } else if (cx != null) { - attr = { - cx: cx, - cy: cy, - r: r - }; - } - return this.el("circle", attr); - }; - - var preload = (function () { - function onerror() { - this.parentNode.removeChild(this); - } - return function (src, f) { - var img = glob.doc.createElement("img"), - body = glob.doc.body; - img.style.cssText = "position:absolute;left:-9999em;top:-9999em"; - img.onload = function () { - f.call(img); - img.onload = img.onerror = null; - body.removeChild(img); - }; - img.onerror = onerror; - body.appendChild(img); - img.src = src; - }; - }()); - - /*\ - * Paper.image - [ method ] - ** - * Places an image on the surface - ** - - src (string) URI of the source image - - x (number) x offset position - - y (number) y offset position - - width (number) width of the image - - height (number) height of the image - = (object) the `image` element - * or - = (object) Snap element object with type `image` - ** - > Usage - | var c = paper.image("apple.png", 10, 10, 80, 80); - \*/ - proto.image = function (src, x, y, width, height) { - var el = this.el("image"); - if (is(src, "object") && "src" in src) { - el.attr(src); - } else if (src != null) { - var set = { - "xlink:href": src, - preserveAspectRatio: "none" - }; - if (x != null && y != null) { - set.x = x; - set.y = y; - } - if (width != null && height != null) { - set.width = width; - set.height = height; - } else { - preload(src, function () { - Snap._.$(el.node, { - width: this.offsetWidth, - height: this.offsetHeight - }); - }); - } - Snap._.$(el.node, set); - } - return el; - }; - /*\ - * Paper.ellipse - [ method ] - ** - * Draws an ellipse - ** - - x (number) x coordinate of the centre - - y (number) y coordinate of the centre - - rx (number) horizontal radius - - ry (number) vertical radius - = (object) the `ellipse` element - ** - > Usage - | var c = paper.ellipse(50, 50, 40, 20); - \*/ - proto.ellipse = function (cx, cy, rx, ry) { - var attr; - if (is(cx, "object") && cx == "[object Object]") { - attr = cx; - } else if (cx != null) { - attr ={ - cx: cx, - cy: cy, - rx: rx, - ry: ry - }; - } - return this.el("ellipse", attr); - }; - // SIERRA Paper.path(): Unclear from the link what a Catmull-Rom curveto is, and why it would make life any easier. - /*\ - * Paper.path - [ method ] - ** - * Creates a `` element using the given string as the path's definition - - pathString (string) #optional path string in SVG format - * Path string consists of one-letter commands, followed by comma seprarated arguments in numerical form. Example: - | "M10,20L30,40" - * This example features two commands: `M`, with arguments `(10, 20)` and `L` with arguments `(30, 40)`. Uppercase letter commands express coordinates in absolute terms, while lowercase commands express them in relative terms from the most recently declared coordinates. - * - #

Here is short list of commands available, for more details see SVG path string format or article about path strings at MDN.

- # - # - # - # - # - # - # - # - # - # - # - #
CommandNameParameters
Mmoveto(x y)+
Zclosepath(none)
Llineto(x y)+
Hhorizontal linetox+
Vvertical linetoy+
Ccurveto(x1 y1 x2 y2 x y)+
Ssmooth curveto(x2 y2 x y)+
Qquadratic Bézier curveto(x1 y1 x y)+
Tsmooth quadratic Bézier curveto(x y)+
Aelliptical arc(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
RCatmull-Rom curveto*x1 y1 (x y)+
- * * _Catmull-Rom curveto_ is a not standard SVG command and added to make life easier. - * Note: there is a special case when a path consists of only three commands: `M10,10R…z`. In this case the path connects back to its starting point. - > Usage - | var c = paper.path("M10 10L90 90"); - | // draw a diagonal line: - | // move to 10,10, line to 90,90 - \*/ - proto.path = function (d) { - var attr; - if (is(d, "object") && !is(d, "array")) { - attr = d; - } else if (d) { - attr = {d: d}; - } - return this.el("path", attr); - }; - /*\ - * Paper.g - [ method ] - ** - * Creates a group element - ** - - varargs (…) #optional elements to nest within the group - = (object) the `g` element - ** - > Usage - | var c1 = paper.circle(), - | c2 = paper.rect(), - | g = paper.g(c2, c1); // note that the order of elements is different - * or - | var c1 = paper.circle(), - | c2 = paper.rect(), - | g = paper.g(); - | g.add(c2, c1); - \*/ - /*\ - * Paper.group - [ method ] - ** - * See @Paper.g - \*/ - proto.group = proto.g = function (first) { - var attr, - el = this.el("g"); - if (arguments.length == 1 && first && !first.type) { - el.attr(first); - } else if (arguments.length) { - el.add(Array.prototype.slice.call(arguments, 0)); - } - return el; - }; - /*\ - * Paper.svg - [ method ] - ** - * Creates a nested SVG element. - - x (number) @optional X of the element - - y (number) @optional Y of the element - - width (number) @optional width of the element - - height (number) @optional height of the element - - vbx (number) @optional viewbox X - - vby (number) @optional viewbox Y - - vbw (number) @optional viewbox width - - vbh (number) @optional viewbox height - ** - = (object) the `svg` element - ** - \*/ - proto.svg = function (x, y, width, height, vbx, vby, vbw, vbh) { - var attrs = {}; - if (is(x, "object") && y == null) { - attrs = x; - } else { - if (x != null) { - attrs.x = x; - } - if (y != null) { - attrs.y = y; - } - if (width != null) { - attrs.width = width; - } - if (height != null) { - attrs.height = height; - } - if (vbx != null && vby != null && vbw != null && vbh != null) { - attrs.viewBox = [vbx, vby, vbw, vbh]; - } - } - return this.el("svg", attrs); - }; - /*\ - * Paper.mask - [ method ] - ** - * Equivalent in behaviour to @Paper.g, except it’s a mask. - ** - = (object) the `mask` element - ** - \*/ - proto.mask = function (first) { - var attr, - el = this.el("mask"); - if (arguments.length == 1 && first && !first.type) { - el.attr(first); - } else if (arguments.length) { - el.add(Array.prototype.slice.call(arguments, 0)); - } - return el; - }; - /*\ - * Paper.ptrn - [ method ] - ** - * Equivalent in behaviour to @Paper.g, except it’s a pattern. - - x (number) @optional X of the element - - y (number) @optional Y of the element - - width (number) @optional width of the element - - height (number) @optional height of the element - - vbx (number) @optional viewbox X - - vby (number) @optional viewbox Y - - vbw (number) @optional viewbox width - - vbh (number) @optional viewbox height - ** - = (object) the `pattern` element - ** - \*/ - proto.ptrn = function (x, y, width, height, vx, vy, vw, vh) { - if (is(x, "object")) { - var attr = x; - } else { - attr = {patternUnits: "userSpaceOnUse"}; - if (x) { - attr.x = x; - } - if (y) { - attr.y = y; - } - if (width != null) { - attr.width = width; - } - if (height != null) { - attr.height = height; - } - if (vx != null && vy != null && vw != null && vh != null) { - attr.viewBox = [vx, vy, vw, vh]; - } else { - attr.viewBox = [x || 0, y || 0, width || 0, height || 0]; - } - } - return this.el("pattern", attr); - }; - /*\ - * Paper.use - [ method ] - ** - * Creates a element. - - id (string) @optional id of element to link - * or - - id (Element) @optional element to link - ** - = (object) the `use` element - ** - \*/ - proto.use = function (id) { - if (id != null) { - if (id instanceof Element) { - if (!id.attr("id")) { - id.attr({id: Snap._.id(id)}); - } - id = id.attr("id"); - } - if (String(id).charAt() == "#") { - id = id.substring(1); - } - return this.el("use", {"xlink:href": "#" + id}); - } else { - return Element.prototype.use.call(this); - } - }; - /*\ - * Paper.symbol - [ method ] - ** - * Creates a element. - - vbx (number) @optional viewbox X - - vby (number) @optional viewbox Y - - vbw (number) @optional viewbox width - - vbh (number) @optional viewbox height - = (object) the `symbol` element - ** - \*/ - proto.symbol = function (vx, vy, vw, vh) { - var attr = {}; - if (vx != null && vy != null && vw != null && vh != null) { - attr.viewBox = [vx, vy, vw, vh]; - } - - return this.el("symbol", attr); - }; - /*\ - * Paper.text - [ method ] - ** - * Draws a text string - ** - - x (number) x coordinate position - - y (number) y coordinate position - - text (string|array) The text string to draw or array of strings to nest within separate `` elements - = (object) the `text` element - ** - > Usage - | var t1 = paper.text(50, 50, "Snap"); - | var t2 = paper.text(50, 50, ["S","n","a","p"]); - | // Text path usage - | t1.attr({textpath: "M10,10L100,100"}); - | // or - | var pth = paper.path("M10,10L100,100"); - | t1.attr({textpath: pth}); - \*/ - proto.text = function (x, y, text) { - var attr = {}; - if (is(x, "object")) { - attr = x; - } else if (x != null) { - attr = { - x: x, - y: y, - text: text || "" - }; - } - return this.el("text", attr); - }; - /*\ - * Paper.line - [ method ] - ** - * Draws a line - ** - - x1 (number) x coordinate position of the start - - y1 (number) y coordinate position of the start - - x2 (number) x coordinate position of the end - - y2 (number) y coordinate position of the end - = (object) the `line` element - ** - > Usage - | var t1 = paper.line(50, 50, 100, 100); - \*/ - proto.line = function (x1, y1, x2, y2) { - var attr = {}; - if (is(x1, "object")) { - attr = x1; - } else if (x1 != null) { - attr = { - x1: x1, - x2: x2, - y1: y1, - y2: y2 - }; - } - return this.el("line", attr); - }; - /*\ - * Paper.polyline - [ method ] - ** - * Draws a polyline - ** - - points (array) array of points - * or - - varargs (…) points - = (object) the `polyline` element - ** - > Usage - | var p1 = paper.polyline([10, 10, 100, 100]); - | var p2 = paper.polyline(10, 10, 100, 100); - \*/ - proto.polyline = function (points) { - if (arguments.length > 1) { - points = Array.prototype.slice.call(arguments, 0); - } - var attr = {}; - if (is(points, "object") && !is(points, "array")) { - attr = points; - } else if (points != null) { - attr = {points: points}; - } - return this.el("polyline", attr); - }; - /*\ - * Paper.polygon - [ method ] - ** - * Draws a polygon. See @Paper.polyline - \*/ - proto.polygon = function (points) { - if (arguments.length > 1) { - points = Array.prototype.slice.call(arguments, 0); - } - var attr = {}; - if (is(points, "object") && !is(points, "array")) { - attr = points; - } else if (points != null) { - attr = {points: points}; - } - return this.el("polygon", attr); - }; - // gradients - (function () { - var $ = Snap._.$; - // gradients' helpers - function Gstops() { - return this.selectAll("stop"); - } - function GaddStop(color, offset) { - var stop = $("stop"), - attr = { - offset: +offset + "%" - }; - color = Snap.color(color); - attr["stop-color"] = color.hex; - if (color.opacity < 1) { - attr["stop-opacity"] = color.opacity; - } - $(stop, attr); - this.node.appendChild(stop); - return this; - } - function GgetBBox() { - if (this.type == "linearGradient") { - var x1 = $(this.node, "x1") || 0, - x2 = $(this.node, "x2") || 1, - y1 = $(this.node, "y1") || 0, - y2 = $(this.node, "y2") || 0; - return Snap._.box(x1, y1, math.abs(x2 - x1), math.abs(y2 - y1)); - } else { - var cx = this.node.cx || .5, - cy = this.node.cy || .5, - r = this.node.r || 0; - return Snap._.box(cx - r, cy - r, r * 2, r * 2); - } - } - function gradient(defs, str) { - var grad = eve("snap.util.grad.parse", null, str).firstDefined(), - el; - if (!grad) { - return null; - } - grad.params.unshift(defs); - if (grad.type.toLowerCase() == "l") { - el = gradientLinear.apply(0, grad.params); - } else { - el = gradientRadial.apply(0, grad.params); - } - if (grad.type != grad.type.toLowerCase()) { - $(el.node, { - gradientUnits: "userSpaceOnUse" - }); - } - var stops = grad.stops, - len = stops.length, - start = 0, - j = 0; - function seed(i, end) { - var step = (end - start) / (i - j); - for (var k = j; k < i; k++) { - stops[k].offset = +(+start + step * (k - j)).toFixed(2); - } - j = i; - start = end; - } - len--; - for (var i = 0; i < len; i++) if ("offset" in stops[i]) { - seed(i, stops[i].offset); - } - stops[len].offset = stops[len].offset || 100; - seed(len, stops[len].offset); - for (i = 0; i <= len; i++) { - var stop = stops[i]; - el.addStop(stop.color, stop.offset); - } - return el; - } - function gradientLinear(defs, x1, y1, x2, y2) { - var el = Snap._.make("linearGradient", defs); - el.stops = Gstops; - el.addStop = GaddStop; - el.getBBox = GgetBBox; - if (x1 != null) { - $(el.node, { - x1: x1, - y1: y1, - x2: x2, - y2: y2 - }); - } - return el; - } - function gradientRadial(defs, cx, cy, r, fx, fy) { - var el = Snap._.make("radialGradient", defs); - el.stops = Gstops; - el.addStop = GaddStop; - el.getBBox = GgetBBox; - if (cx != null) { - $(el.node, { - cx: cx, - cy: cy, - r: r - }); - } - if (fx != null && fy != null) { - $(el.node, { - fx: fx, - fy: fy - }); - } - return el; - } - /*\ - * Paper.gradient - [ method ] - ** - * Creates a gradient element - ** - - gradient (string) gradient descriptor - > Gradient Descriptor - * The gradient descriptor is an expression formatted as - * follows: `()`. The `` can be - * either linear or radial. The uppercase `L` or `R` letters - * indicate absolute coordinates offset from the SVG surface. - * Lowercase `l` or `r` letters indicate coordinates - * calculated relative to the element to which the gradient is - * applied. Coordinates specify a linear gradient vector as - * `x1`, `y1`, `x2`, `y2`, or a radial gradient as `cx`, `cy`, - * `r` and optional `fx`, `fy` specifying a focal point away - * from the center of the circle. Specify `` as a list - * of dash-separated CSS color values. Each color may be - * followed by a custom offset value, separated with a colon - * character. - > Examples - * Linear gradient, relative from top-left corner to bottom-right - * corner, from black through red to white: - | var g = paper.gradient("l(0, 0, 1, 1)#000-#f00-#fff"); - * Linear gradient, absolute from (0, 0) to (100, 100), from black - * through red at 25% to white: - | var g = paper.gradient("L(0, 0, 100, 100)#000-#f00:25-#fff"); - * Radial gradient, relative from the center of the element with radius - * half the width, from black to white: - | var g = paper.gradient("r(0.5, 0.5, 0.5)#000-#fff"); - * To apply the gradient: - | paper.circle(50, 50, 40).attr({ - | fill: g - | }); - = (object) the `gradient` element - \*/ - proto.gradient = function (str) { - return gradient(this.defs, str); - }; - proto.gradientLinear = function (x1, y1, x2, y2) { - return gradientLinear(this.defs, x1, y1, x2, y2); - }; - proto.gradientRadial = function (cx, cy, r, fx, fy) { - return gradientRadial(this.defs, cx, cy, r, fx, fy); - }; - /*\ - * Paper.toString - [ method ] - ** - * Returns SVG code for the @Paper - = (string) SVG code for the @Paper - \*/ - proto.toString = function () { - var doc = this.node.ownerDocument, - f = doc.createDocumentFragment(), - d = doc.createElement("div"), - svg = this.node.cloneNode(true), - res; - f.appendChild(d); - d.appendChild(svg); - Snap._.$(svg, {xmlns: "http://www.w3.org/2000/svg"}); - res = d.innerHTML; - f.removeChild(f.firstChild); - return res; - }; - /*\ - * Paper.toDataURL - [ method ] - ** - * Returns SVG code for the @Paper as Data URI string. - = (string) Data URI string - \*/ - proto.toDataURL = function () { - if (window && window.btoa) { - return "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(this))); - } - }; - /*\ - * Paper.clear - [ method ] - ** - * Removes all child nodes of the paper, except . - \*/ - proto.clear = function () { - var node = this.node.firstChild, - next; - while (node) { - next = node.nextSibling; - if (node.tagName != "defs") { - node.parentNode.removeChild(node); - } else { - proto.clear.call({node: node}); - } - node = next; - } - }; - }()); - }); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob) { - var elproto = Element.prototype, - is = Snap.is, - clone = Snap._.clone, - has = "hasOwnProperty", - p2s = /,?([a-z]),?/gi, - toFloat = parseFloat, - math = Math, - PI = math.PI, - mmin = math.min, - mmax = math.max, - pow = math.pow, - abs = math.abs; - function paths(ps) { - var p = paths.ps = paths.ps || {}; - if (p[ps]) { - p[ps].sleep = 100; - } else { - p[ps] = { - sleep: 100 - }; - } - setTimeout(function () { - for (var key in p) if (p[has](key) && key != ps) { - p[key].sleep--; - !p[key].sleep && delete p[key]; - } - }); - return p[ps]; - } - function box(x, y, width, height) { - if (x == null) { - x = y = width = height = 0; - } - if (y == null) { - y = x.y; - width = x.width; - height = x.height; - x = x.x; - } - return { - x: x, - y: y, - width: width, - w: width, - height: height, - h: height, - x2: x + width, - y2: y + height, - cx: x + width / 2, - cy: y + height / 2, - r1: math.min(width, height) / 2, - r2: math.max(width, height) / 2, - r0: math.sqrt(width * width + height * height) / 2, - path: rectPath(x, y, width, height), - vb: [x, y, width, height].join(" ") - }; - } - function toString() { - return this.join(",").replace(p2s, "$1"); - } - function pathClone(pathArray) { - var res = clone(pathArray); - res.toString = toString; - return res; - } - function getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { - if (length == null) { - return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y); - } else { - return findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, - getTotLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length)); - } - } - function getLengthFactory(istotal, subpath) { - function O(val) { - return +(+val).toFixed(3); - } - return Snap._.cacher(function (path, length, onlystart) { - if (path instanceof Element) { - path = path.attr("d"); - } - path = path2curve(path); - var x, y, p, l, sp = "", subpaths = {}, point, - len = 0; - for (var i = 0, ii = path.length; i < ii; i++) { - p = path[i]; - if (p[0] == "M") { - x = +p[1]; - y = +p[2]; - } else { - l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); - if (len + l > length) { - if (subpath && !subpaths.start) { - point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); - sp += [ - "C" + O(point.start.x), - O(point.start.y), - O(point.m.x), - O(point.m.y), - O(point.x), - O(point.y) - ]; - if (onlystart) {return sp;} - subpaths.start = sp; - sp = [ - "M" + O(point.x), - O(point.y) + "C" + O(point.n.x), - O(point.n.y), - O(point.end.x), - O(point.end.y), - O(p[5]), - O(p[6]) - ].join(); - len += l; - x = +p[5]; - y = +p[6]; - continue; - } - if (!istotal && !subpath) { - point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); - return point; - } - } - len += l; - x = +p[5]; - y = +p[6]; - } - sp += p.shift() + p; - } - subpaths.end = sp; - point = istotal ? len : subpath ? subpaths : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1); - return point; - }, null, Snap._.clone); - } - var getTotalLength = getLengthFactory(1), - getPointAtLength = getLengthFactory(), - getSubpathsAtLength = getLengthFactory(0, 1); - function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { - var t1 = 1 - t, - t13 = pow(t1, 3), - t12 = pow(t1, 2), - t2 = t * t, - t3 = t2 * t, - x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x, - y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y, - mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x), - my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y), - nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x), - ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y), - ax = t1 * p1x + t * c1x, - ay = t1 * p1y + t * c1y, - cx = t1 * c2x + t * p2x, - cy = t1 * c2y + t * p2y, - alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI); - // (mx > nx || my < ny) && (alpha += 180); - return { - x: x, - y: y, - m: {x: mx, y: my}, - n: {x: nx, y: ny}, - start: {x: ax, y: ay}, - end: {x: cx, y: cy}, - alpha: alpha - }; - } - function bezierBBox(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { - if (!Snap.is(p1x, "array")) { - p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y]; - } - var bbox = curveDim.apply(null, p1x); - return box( - bbox.min.x, - bbox.min.y, - bbox.max.x - bbox.min.x, - bbox.max.y - bbox.min.y - ); - } - function isPointInsideBBox(bbox, x, y) { - return x >= bbox.x && - x <= bbox.x + bbox.width && - y >= bbox.y && - y <= bbox.y + bbox.height; - } - function isBBoxIntersect(bbox1, bbox2) { - bbox1 = box(bbox1); - bbox2 = box(bbox2); - return isPointInsideBBox(bbox2, bbox1.x, bbox1.y) - || isPointInsideBBox(bbox2, bbox1.x2, bbox1.y) - || isPointInsideBBox(bbox2, bbox1.x, bbox1.y2) - || isPointInsideBBox(bbox2, bbox1.x2, bbox1.y2) - || isPointInsideBBox(bbox1, bbox2.x, bbox2.y) - || isPointInsideBBox(bbox1, bbox2.x2, bbox2.y) - || isPointInsideBBox(bbox1, bbox2.x, bbox2.y2) - || isPointInsideBBox(bbox1, bbox2.x2, bbox2.y2) - || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x - || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x) - && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y - || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y); - } - function base3(t, p1, p2, p3, p4) { - var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4, - t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3; - return t * t2 - 3 * p1 + 3 * p2; - } - function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) { - if (z == null) { - z = 1; - } - z = z > 1 ? 1 : z < 0 ? 0 : z; - var z2 = z / 2, - n = 12, - Tvalues = [-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816], - Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472], - sum = 0; - for (var i = 0; i < n; i++) { - var ct = z2 * Tvalues[i] + z2, - xbase = base3(ct, x1, x2, x3, x4), - ybase = base3(ct, y1, y2, y3, y4), - comb = xbase * xbase + ybase * ybase; - sum += Cvalues[i] * math.sqrt(comb); - } - return z2 * sum; - } - function getTotLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) { - if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) { - return; - } - var t = 1, - step = t / 2, - t2 = t - step, - l, - e = .01; - l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); - while (abs(l - ll) > e) { - step /= 2; - t2 += (l < ll ? 1 : -1) * step; - l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); - } - return t2; - } - function intersect(x1, y1, x2, y2, x3, y3, x4, y4) { - if ( - mmax(x1, x2) < mmin(x3, x4) || - mmin(x1, x2) > mmax(x3, x4) || - mmax(y1, y2) < mmin(y3, y4) || - mmin(y1, y2) > mmax(y3, y4) - ) { - return; - } - var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4), - ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4), - denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); - - if (!denominator) { - return; - } - var px = nx / denominator, - py = ny / denominator, - px2 = +px.toFixed(2), - py2 = +py.toFixed(2); - if ( - px2 < +mmin(x1, x2).toFixed(2) || - px2 > +mmax(x1, x2).toFixed(2) || - px2 < +mmin(x3, x4).toFixed(2) || - px2 > +mmax(x3, x4).toFixed(2) || - py2 < +mmin(y1, y2).toFixed(2) || - py2 > +mmax(y1, y2).toFixed(2) || - py2 < +mmin(y3, y4).toFixed(2) || - py2 > +mmax(y3, y4).toFixed(2) - ) { - return; - } - return {x: px, y: py}; - } - function inter(bez1, bez2) { - return interHelper(bez1, bez2); - } - function interCount(bez1, bez2) { - return interHelper(bez1, bez2, 1); - } - function interHelper(bez1, bez2, justCount) { - var bbox1 = bezierBBox(bez1), - bbox2 = bezierBBox(bez2); - if (!isBBoxIntersect(bbox1, bbox2)) { - return justCount ? 0 : []; - } - var l1 = bezlen.apply(0, bez1), - l2 = bezlen.apply(0, bez2), - n1 = ~~(l1 / 8), - n2 = ~~(l2 / 8), - dots1 = [], - dots2 = [], - xy = {}, - res = justCount ? 0 : []; - for (var i = 0; i < n1 + 1; i++) { - var p = findDotsAtSegment.apply(0, bez1.concat(i / n1)); - dots1.push({x: p.x, y: p.y, t: i / n1}); - } - for (i = 0; i < n2 + 1; i++) { - p = findDotsAtSegment.apply(0, bez2.concat(i / n2)); - dots2.push({x: p.x, y: p.y, t: i / n2}); - } - for (i = 0; i < n1; i++) { - for (var j = 0; j < n2; j++) { - var di = dots1[i], - di1 = dots1[i + 1], - dj = dots2[j], - dj1 = dots2[j + 1], - ci = abs(di1.x - di.x) < .001 ? "y" : "x", - cj = abs(dj1.x - dj.x) < .001 ? "y" : "x", - is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y); - if (is) { - if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) { - continue; - } - xy[is.x.toFixed(4)] = is.y.toFixed(4); - var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t), - t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t); - if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) { - if (justCount) { - res++; - } else { - res.push({ - x: is.x, - y: is.y, - t1: t1, - t2: t2 - }); - } - } - } - } - } - return res; - } - function pathIntersection(path1, path2) { - return interPathHelper(path1, path2); - } - function pathIntersectionNumber(path1, path2) { - return interPathHelper(path1, path2, 1); - } - function interPathHelper(path1, path2, justCount) { - path1 = path2curve(path1); - path2 = path2curve(path2); - var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2, - res = justCount ? 0 : []; - for (var i = 0, ii = path1.length; i < ii; i++) { - var pi = path1[i]; - if (pi[0] == "M") { - x1 = x1m = pi[1]; - y1 = y1m = pi[2]; - } else { - if (pi[0] == "C") { - bez1 = [x1, y1].concat(pi.slice(1)); - x1 = bez1[6]; - y1 = bez1[7]; - } else { - bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m]; - x1 = x1m; - y1 = y1m; - } - for (var j = 0, jj = path2.length; j < jj; j++) { - var pj = path2[j]; - if (pj[0] == "M") { - x2 = x2m = pj[1]; - y2 = y2m = pj[2]; - } else { - if (pj[0] == "C") { - bez2 = [x2, y2].concat(pj.slice(1)); - x2 = bez2[6]; - y2 = bez2[7]; - } else { - bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m]; - x2 = x2m; - y2 = y2m; - } - var intr = interHelper(bez1, bez2, justCount); - if (justCount) { - res += intr; - } else { - for (var k = 0, kk = intr.length; k < kk; k++) { - intr[k].segment1 = i; - intr[k].segment2 = j; - intr[k].bez1 = bez1; - intr[k].bez2 = bez2; - } - res = res.concat(intr); - } - } - } - } - } - return res; - } - function isPointInsidePath(path, x, y) { - var bbox = pathBBox(path); - return isPointInsideBBox(bbox, x, y) && - interPathHelper(path, [["M", x, y], ["H", bbox.x2 + 10]], 1) % 2 == 1; - } - function pathBBox(path) { - var pth = paths(path); - if (pth.bbox) { - return clone(pth.bbox); - } - if (!path) { - return box(); - } - path = path2curve(path); - var x = 0, - y = 0, - X = [], - Y = [], - p; - for (var i = 0, ii = path.length; i < ii; i++) { - p = path[i]; - if (p[0] == "M") { - x = p[1]; - y = p[2]; - X.push(x); - Y.push(y); - } else { - var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); - X = X.concat(dim.min.x, dim.max.x); - Y = Y.concat(dim.min.y, dim.max.y); - x = p[5]; - y = p[6]; - } - } - var xmin = mmin.apply(0, X), - ymin = mmin.apply(0, Y), - xmax = mmax.apply(0, X), - ymax = mmax.apply(0, Y), - bb = box(xmin, ymin, xmax - xmin, ymax - ymin); - pth.bbox = clone(bb); - return bb; - } - function rectPath(x, y, w, h, r) { - if (r) { - return [ - ["M", +x + (+r), y], - ["l", w - r * 2, 0], - ["a", r, r, 0, 0, 1, r, r], - ["l", 0, h - r * 2], - ["a", r, r, 0, 0, 1, -r, r], - ["l", r * 2 - w, 0], - ["a", r, r, 0, 0, 1, -r, -r], - ["l", 0, r * 2 - h], - ["a", r, r, 0, 0, 1, r, -r], - ["z"] - ]; - } - var res = [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; - res.toString = toString; - return res; - } - function ellipsePath(x, y, rx, ry, a) { - if (a == null && ry == null) { - ry = rx; - } - x = +x; - y = +y; - rx = +rx; - ry = +ry; - if (a != null) { - var rad = Math.PI / 180, - x1 = x + rx * Math.cos(-ry * rad), - x2 = x + rx * Math.cos(-a * rad), - y1 = y + rx * Math.sin(-ry * rad), - y2 = y + rx * Math.sin(-a * rad), - res = [["M", x1, y1], ["A", rx, rx, 0, +(a - ry > 180), 0, x2, y2]]; - } else { - res = [ - ["M", x, y], - ["m", 0, -ry], - ["a", rx, ry, 0, 1, 1, 0, 2 * ry], - ["a", rx, ry, 0, 1, 1, 0, -2 * ry], - ["z"] - ]; - } - res.toString = toString; - return res; - } - var unit2px = Snap._unit2px, - getPath = { - path: function (el) { - return el.attr("path"); - }, - circle: function (el) { - var attr = unit2px(el); - return ellipsePath(attr.cx, attr.cy, attr.r); - }, - ellipse: function (el) { - var attr = unit2px(el); - return ellipsePath(attr.cx || 0, attr.cy || 0, attr.rx, attr.ry); - }, - rect: function (el) { - var attr = unit2px(el); - return rectPath(attr.x || 0, attr.y || 0, attr.width, attr.height, attr.rx, attr.ry); - }, - image: function (el) { - var attr = unit2px(el); - return rectPath(attr.x || 0, attr.y || 0, attr.width, attr.height); - }, - line: function (el) { - return "M" + [el.attr("x1") || 0, el.attr("y1") || 0, el.attr("x2"), el.attr("y2")]; - }, - polyline: function (el) { - return "M" + el.attr("points"); - }, - polygon: function (el) { - return "M" + el.attr("points") + "z"; - }, - deflt: function (el) { - var bbox = el.node.getBBox(); - return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); - } - }; - function pathToRelative(pathArray) { - var pth = paths(pathArray), - lowerCase = String.prototype.toLowerCase; - if (pth.rel) { - return pathClone(pth.rel); - } - if (!Snap.is(pathArray, "array") || !Snap.is(pathArray && pathArray[0], "array")) { - pathArray = Snap.parsePathString(pathArray); - } - var res = [], - x = 0, - y = 0, - mx = 0, - my = 0, - start = 0; - if (pathArray[0][0] == "M") { - x = pathArray[0][1]; - y = pathArray[0][2]; - mx = x; - my = y; - start++; - res.push(["M", x, y]); - } - for (var i = start, ii = pathArray.length; i < ii; i++) { - var r = res[i] = [], - pa = pathArray[i]; - if (pa[0] != lowerCase.call(pa[0])) { - r[0] = lowerCase.call(pa[0]); - switch (r[0]) { - case "a": - r[1] = pa[1]; - r[2] = pa[2]; - r[3] = pa[3]; - r[4] = pa[4]; - r[5] = pa[5]; - r[6] = +(pa[6] - x).toFixed(3); - r[7] = +(pa[7] - y).toFixed(3); - break; - case "v": - r[1] = +(pa[1] - y).toFixed(3); - break; - case "m": - mx = pa[1]; - my = pa[2]; - default: - for (var j = 1, jj = pa.length; j < jj; j++) { - r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3); - } - } - } else { - r = res[i] = []; - if (pa[0] == "m") { - mx = pa[1] + x; - my = pa[2] + y; - } - for (var k = 0, kk = pa.length; k < kk; k++) { - res[i][k] = pa[k]; - } - } - var len = res[i].length; - switch (res[i][0]) { - case "z": - x = mx; - y = my; - break; - case "h": - x += +res[i][len - 1]; - break; - case "v": - y += +res[i][len - 1]; - break; - default: - x += +res[i][len - 2]; - y += +res[i][len - 1]; - } - } - res.toString = toString; - pth.rel = pathClone(res); - return res; - } - function pathToAbsolute(pathArray) { - var pth = paths(pathArray); - if (pth.abs) { - return pathClone(pth.abs); - } - if (!is(pathArray, "array") || !is(pathArray && pathArray[0], "array")) { // rough assumption - pathArray = Snap.parsePathString(pathArray); - } - if (!pathArray || !pathArray.length) { - return [["M", 0, 0]]; - } - var res = [], - x = 0, - y = 0, - mx = 0, - my = 0, - start = 0, - pa0; - if (pathArray[0][0] == "M") { - x = +pathArray[0][1]; - y = +pathArray[0][2]; - mx = x; - my = y; - start++; - res[0] = ["M", x, y]; - } - var crz = pathArray.length == 3 && - pathArray[0][0] == "M" && - pathArray[1][0].toUpperCase() == "R" && - pathArray[2][0].toUpperCase() == "Z"; - for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) { - res.push(r = []); - pa = pathArray[i]; - pa0 = pa[0]; - if (pa0 != pa0.toUpperCase()) { - r[0] = pa0.toUpperCase(); - switch (r[0]) { - case "A": - r[1] = pa[1]; - r[2] = pa[2]; - r[3] = pa[3]; - r[4] = pa[4]; - r[5] = pa[5]; - r[6] = +pa[6] + x; - r[7] = +pa[7] + y; - break; - case "V": - r[1] = +pa[1] + y; - break; - case "H": - r[1] = +pa[1] + x; - break; - case "R": - var dots = [x, y].concat(pa.slice(1)); - for (var j = 2, jj = dots.length; j < jj; j++) { - dots[j] = +dots[j] + x; - dots[++j] = +dots[j] + y; - } - res.pop(); - res = res.concat(catmullRom2bezier(dots, crz)); - break; - case "O": - res.pop(); - dots = ellipsePath(x, y, pa[1], pa[2]); - dots.push(dots[0]); - res = res.concat(dots); - break; - case "U": - res.pop(); - res = res.concat(ellipsePath(x, y, pa[1], pa[2], pa[3])); - r = ["U"].concat(res[res.length - 1].slice(-2)); - break; - case "M": - mx = +pa[1] + x; - my = +pa[2] + y; - default: - for (j = 1, jj = pa.length; j < jj; j++) { - r[j] = +pa[j] + ((j % 2) ? x : y); - } - } - } else if (pa0 == "R") { - dots = [x, y].concat(pa.slice(1)); - res.pop(); - res = res.concat(catmullRom2bezier(dots, crz)); - r = ["R"].concat(pa.slice(-2)); - } else if (pa0 == "O") { - res.pop(); - dots = ellipsePath(x, y, pa[1], pa[2]); - dots.push(dots[0]); - res = res.concat(dots); - } else if (pa0 == "U") { - res.pop(); - res = res.concat(ellipsePath(x, y, pa[1], pa[2], pa[3])); - r = ["U"].concat(res[res.length - 1].slice(-2)); - } else { - for (var k = 0, kk = pa.length; k < kk; k++) { - r[k] = pa[k]; - } - } - pa0 = pa0.toUpperCase(); - if (pa0 != "O") { - switch (r[0]) { - case "Z": - x = +mx; - y = +my; - break; - case "H": - x = r[1]; - break; - case "V": - y = r[1]; - break; - case "M": - mx = r[r.length - 2]; - my = r[r.length - 1]; - default: - x = r[r.length - 2]; - y = r[r.length - 1]; - } - } - } - res.toString = toString; - pth.abs = pathClone(res); - return res; - } - function l2c(x1, y1, x2, y2) { - return [x1, y1, x2, y2, x2, y2]; - } - function q2c(x1, y1, ax, ay, x2, y2) { - var _13 = 1 / 3, - _23 = 2 / 3; - return [ - _13 * x1 + _23 * ax, - _13 * y1 + _23 * ay, - _13 * x2 + _23 * ax, - _13 * y2 + _23 * ay, - x2, - y2 - ]; - } - function a2c(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { - // for more information of where this math came from visit: - // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes - var _120 = PI * 120 / 180, - rad = PI / 180 * (+angle || 0), - res = [], - xy, - rotate = Snap._.cacher(function (x, y, rad) { - var X = x * math.cos(rad) - y * math.sin(rad), - Y = x * math.sin(rad) + y * math.cos(rad); - return {x: X, y: Y}; - }); - if (!recursive) { - xy = rotate(x1, y1, -rad); - x1 = xy.x; - y1 = xy.y; - xy = rotate(x2, y2, -rad); - x2 = xy.x; - y2 = xy.y; - var cos = math.cos(PI / 180 * angle), - sin = math.sin(PI / 180 * angle), - x = (x1 - x2) / 2, - y = (y1 - y2) / 2; - var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); - if (h > 1) { - h = math.sqrt(h); - rx = h * rx; - ry = h * ry; - } - var rx2 = rx * rx, - ry2 = ry * ry, - k = (large_arc_flag == sweep_flag ? -1 : 1) * - math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), - cx = k * rx * y / ry + (x1 + x2) / 2, - cy = k * -ry * x / rx + (y1 + y2) / 2, - f1 = math.asin(((y1 - cy) / ry).toFixed(9)), - f2 = math.asin(((y2 - cy) / ry).toFixed(9)); - - f1 = x1 < cx ? PI - f1 : f1; - f2 = x2 < cx ? PI - f2 : f2; - f1 < 0 && (f1 = PI * 2 + f1); - f2 < 0 && (f2 = PI * 2 + f2); - if (sweep_flag && f1 > f2) { - f1 = f1 - PI * 2; - } - if (!sweep_flag && f2 > f1) { - f2 = f2 - PI * 2; - } - } else { - f1 = recursive[0]; - f2 = recursive[1]; - cx = recursive[2]; - cy = recursive[3]; - } - var df = f2 - f1; - if (abs(df) > _120) { - var f2old = f2, - x2old = x2, - y2old = y2; - f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); - x2 = cx + rx * math.cos(f2); - y2 = cy + ry * math.sin(f2); - res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); - } - df = f2 - f1; - var c1 = math.cos(f1), - s1 = math.sin(f1), - c2 = math.cos(f2), - s2 = math.sin(f2), - t = math.tan(df / 4), - hx = 4 / 3 * rx * t, - hy = 4 / 3 * ry * t, - m1 = [x1, y1], - m2 = [x1 + hx * s1, y1 - hy * c1], - m3 = [x2 + hx * s2, y2 - hy * c2], - m4 = [x2, y2]; - m2[0] = 2 * m1[0] - m2[0]; - m2[1] = 2 * m1[1] - m2[1]; - if (recursive) { - return [m2, m3, m4].concat(res); - } else { - res = [m2, m3, m4].concat(res).join().split(","); - var newres = []; - for (var i = 0, ii = res.length; i < ii; i++) { - newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; - } - return newres; - } - } - function findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { - var t1 = 1 - t; - return { - x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, - y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y - }; - } - - // Returns bounding box of cubic bezier curve. - // Source: http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html - // Original version: NISHIO Hirokazu - // Modifications: https://github.com/timo22345 - function curveDim(x0, y0, x1, y1, x2, y2, x3, y3) { - var tvalues = [], - bounds = [[], []], - a, b, c, t, t1, t2, b2ac, sqrtb2ac; - for (var i = 0; i < 2; ++i) { - if (i == 0) { - b = 6 * x0 - 12 * x1 + 6 * x2; - a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3; - c = 3 * x1 - 3 * x0; - } else { - b = 6 * y0 - 12 * y1 + 6 * y2; - a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3; - c = 3 * y1 - 3 * y0; - } - if (abs(a) < 1e-12) { - if (abs(b) < 1e-12) { - continue; - } - t = -c / b; - if (0 < t && t < 1) { - tvalues.push(t); - } - continue; - } - b2ac = b * b - 4 * c * a; - sqrtb2ac = math.sqrt(b2ac); - if (b2ac < 0) { - continue; - } - t1 = (-b + sqrtb2ac) / (2 * a); - if (0 < t1 && t1 < 1) { - tvalues.push(t1); - } - t2 = (-b - sqrtb2ac) / (2 * a); - if (0 < t2 && t2 < 1) { - tvalues.push(t2); - } - } - - var x, y, j = tvalues.length, - jlen = j, - mt; - while (j--) { - t = tvalues[j]; - mt = 1 - t; - bounds[0][j] = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3); - bounds[1][j] = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3); - } - - bounds[0][jlen] = x0; - bounds[1][jlen] = y0; - bounds[0][jlen + 1] = x3; - bounds[1][jlen + 1] = y3; - bounds[0].length = bounds[1].length = jlen + 2; - - - return { - min: {x: mmin.apply(0, bounds[0]), y: mmin.apply(0, bounds[1])}, - max: {x: mmax.apply(0, bounds[0]), y: mmax.apply(0, bounds[1])} - }; - } - - function path2curve(path, path2) { - var pth = !path2 && paths(path); - if (!path2 && pth.curve) { - return pathClone(pth.curve); - } - var p = pathToAbsolute(path), - p2 = path2 && pathToAbsolute(path2), - attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, - attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, - processPath = function (path, d, pcom) { - var nx, ny; - if (!path) { - return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; - } - !(path[0] in {T: 1, Q: 1}) && (d.qx = d.qy = null); - switch (path[0]) { - case "M": - d.X = path[1]; - d.Y = path[2]; - break; - case "A": - path = ["C"].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1)))); - break; - case "S": - if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S. - nx = d.x * 2 - d.bx; // And reflect the previous - ny = d.y * 2 - d.by; // command's control point relative to the current point. - } - else { // or some else or nothing - nx = d.x; - ny = d.y; - } - path = ["C", nx, ny].concat(path.slice(1)); - break; - case "T": - if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T. - d.qx = d.x * 2 - d.qx; // And make a reflection similar - d.qy = d.y * 2 - d.qy; // to case "S". - } - else { // or something else or nothing - d.qx = d.x; - d.qy = d.y; - } - path = ["C"].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); - break; - case "Q": - d.qx = path[1]; - d.qy = path[2]; - path = ["C"].concat(q2c(d.x, d.y, path[1], path[2], path[3], path[4])); - break; - case "L": - path = ["C"].concat(l2c(d.x, d.y, path[1], path[2])); - break; - case "H": - path = ["C"].concat(l2c(d.x, d.y, path[1], d.y)); - break; - case "V": - path = ["C"].concat(l2c(d.x, d.y, d.x, path[1])); - break; - case "Z": - path = ["C"].concat(l2c(d.x, d.y, d.X, d.Y)); - break; - } - return path; - }, - fixArc = function (pp, i) { - if (pp[i].length > 7) { - pp[i].shift(); - var pi = pp[i]; - while (pi.length) { - pcoms1[i] = "A"; // if created multiple C:s, their original seg is saved - p2 && (pcoms2[i] = "A"); // the same as above - pp.splice(i++, 0, ["C"].concat(pi.splice(0, 6))); - } - pp.splice(i, 1); - ii = mmax(p.length, p2 && p2.length || 0); - } - }, - fixM = function (path1, path2, a1, a2, i) { - if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { - path2.splice(i, 0, ["M", a2.x, a2.y]); - a1.bx = 0; - a1.by = 0; - a1.x = path1[i][1]; - a1.y = path1[i][2]; - ii = mmax(p.length, p2 && p2.length || 0); - } - }, - pcoms1 = [], // path commands of original path p - pcoms2 = [], // path commands of original path p2 - pfirst = "", // temporary holder for original path command - pcom = ""; // holder for previous path command of original path - for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) { - p[i] && (pfirst = p[i][0]); // save current path command - - if (pfirst != "C") // C is not saved yet, because it may be result of conversion - { - pcoms1[i] = pfirst; // Save current path command - i && ( pcom = pcoms1[i - 1]); // Get previous path command pcom - } - p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath - - if (pcoms1[i] != "A" && pfirst == "C") pcoms1[i] = "C"; // A is the only command - // which may produce multiple C:s - // so we have to make sure that C is also C in original path - - fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1 - - if (p2) { // the same procedures is done to p2 - p2[i] && (pfirst = p2[i][0]); - if (pfirst != "C") { - pcoms2[i] = pfirst; - i && (pcom = pcoms2[i - 1]); - } - p2[i] = processPath(p2[i], attrs2, pcom); - - if (pcoms2[i] != "A" && pfirst == "C") { - pcoms2[i] = "C"; - } - - fixArc(p2, i); - } - fixM(p, p2, attrs, attrs2, i); - fixM(p2, p, attrs2, attrs, i); - var seg = p[i], - seg2 = p2 && p2[i], - seglen = seg.length, - seg2len = p2 && seg2.length; - attrs.x = seg[seglen - 2]; - attrs.y = seg[seglen - 1]; - attrs.bx = toFloat(seg[seglen - 4]) || attrs.x; - attrs.by = toFloat(seg[seglen - 3]) || attrs.y; - attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x); - attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y); - attrs2.x = p2 && seg2[seg2len - 2]; - attrs2.y = p2 && seg2[seg2len - 1]; - } - if (!p2) { - pth.curve = pathClone(p); - } - return p2 ? [p, p2] : p; - } - function mapPath(path, matrix) { - if (!matrix) { - return path; - } - var x, y, i, j, ii, jj, pathi; - path = path2curve(path); - for (i = 0, ii = path.length; i < ii; i++) { - pathi = path[i]; - for (j = 1, jj = pathi.length; j < jj; j += 2) { - x = matrix.x(pathi[j], pathi[j + 1]); - y = matrix.y(pathi[j], pathi[j + 1]); - pathi[j] = x; - pathi[j + 1] = y; - } - } - return path; - } - - // http://schepers.cc/getting-to-the-point - function catmullRom2bezier(crp, z) { - var d = []; - for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) { - var p = [ - {x: +crp[i - 2], y: +crp[i - 1]}, - {x: +crp[i], y: +crp[i + 1]}, - {x: +crp[i + 2], y: +crp[i + 3]}, - {x: +crp[i + 4], y: +crp[i + 5]} - ]; - if (z) { - if (!i) { - p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]}; - } else if (iLen - 4 == i) { - p[3] = {x: +crp[0], y: +crp[1]}; - } else if (iLen - 2 == i) { - p[2] = {x: +crp[0], y: +crp[1]}; - p[3] = {x: +crp[2], y: +crp[3]}; - } - } else { - if (iLen - 4 == i) { - p[3] = p[2]; - } else if (!i) { - p[0] = {x: +crp[i], y: +crp[i + 1]}; - } - } - d.push(["C", - (-p[0].x + 6 * p[1].x + p[2].x) / 6, - (-p[0].y + 6 * p[1].y + p[2].y) / 6, - (p[1].x + 6 * p[2].x - p[3].x) / 6, - (p[1].y + 6*p[2].y - p[3].y) / 6, - p[2].x, - p[2].y - ]); - } - - return d; - } - - // export - Snap.path = paths; - - /*\ - * Snap.path.getTotalLength - [ method ] - ** - * Returns the length of the given path in pixels - ** - - path (string) SVG path string - ** - = (number) length - \*/ - Snap.path.getTotalLength = getTotalLength; - /*\ - * Snap.path.getPointAtLength - [ method ] - ** - * Returns the coordinates of the point located at the given length along the given path - ** - - path (string) SVG path string - - length (number) length, in pixels, from the start of the path, excluding non-rendering jumps - ** - = (object) representation of the point: - o { - o x: (number) x coordinate, - o y: (number) y coordinate, - o alpha: (number) angle of derivative - o } - \*/ - Snap.path.getPointAtLength = getPointAtLength; - /*\ - * Snap.path.getSubpath - [ method ] - ** - * Returns the subpath of a given path between given start and end lengths - ** - - path (string) SVG path string - - from (number) length, in pixels, from the start of the path to the start of the segment - - to (number) length, in pixels, from the start of the path to the end of the segment - ** - = (string) path string definition for the segment - \*/ - Snap.path.getSubpath = function (path, from, to) { - if (this.getTotalLength(path) - to < 1e-6) { - return getSubpathsAtLength(path, from).end; - } - var a = getSubpathsAtLength(path, to, 1); - return from ? getSubpathsAtLength(a, from).end : a; - }; - /*\ - * Element.getTotalLength - [ method ] - ** - * Returns the length of the path in pixels (only works for `path` elements) - = (number) length - \*/ - elproto.getTotalLength = function () { - if (this.node.getTotalLength) { - return this.node.getTotalLength(); - } - }; - // SIERRA Element.getPointAtLength()/Element.getTotalLength(): If a is broken into different segments, is the jump distance to the new coordinates set by the _M_ or _m_ commands calculated as part of the path's total length? - /*\ - * Element.getPointAtLength - [ method ] - ** - * Returns coordinates of the point located at the given length on the given path (only works for `path` elements) - ** - - length (number) length, in pixels, from the start of the path, excluding non-rendering jumps - ** - = (object) representation of the point: - o { - o x: (number) x coordinate, - o y: (number) y coordinate, - o alpha: (number) angle of derivative - o } - \*/ - elproto.getPointAtLength = function (length) { - return getPointAtLength(this.attr("d"), length); - }; - // SIERRA Element.getSubpath(): Similar to the problem for Element.getPointAtLength(). Unclear how this would work for a segmented path. Overall, the concept of _subpath_ and what I'm calling a _segment_ (series of non-_M_ or _Z_ commands) is unclear. - /*\ - * Element.getSubpath - [ method ] - ** - * Returns subpath of a given element from given start and end lengths (only works for `path` elements) - ** - - from (number) length, in pixels, from the start of the path to the start of the segment - - to (number) length, in pixels, from the start of the path to the end of the segment - ** - = (string) path string definition for the segment - \*/ - elproto.getSubpath = function (from, to) { - return Snap.path.getSubpath(this.attr("d"), from, to); - }; - Snap._.box = box; - /*\ - * Snap.path.findDotsAtSegment - [ method ] - ** - * Utility method - ** - * Finds dot coordinates on the given cubic beziér curve at the given t - - p1x (number) x of the first point of the curve - - p1y (number) y of the first point of the curve - - c1x (number) x of the first anchor of the curve - - c1y (number) y of the first anchor of the curve - - c2x (number) x of the second anchor of the curve - - c2y (number) y of the second anchor of the curve - - p2x (number) x of the second point of the curve - - p2y (number) y of the second point of the curve - - t (number) position on the curve (0..1) - = (object) point information in format: - o { - o x: (number) x coordinate of the point, - o y: (number) y coordinate of the point, - o m: { - o x: (number) x coordinate of the left anchor, - o y: (number) y coordinate of the left anchor - o }, - o n: { - o x: (number) x coordinate of the right anchor, - o y: (number) y coordinate of the right anchor - o }, - o start: { - o x: (number) x coordinate of the start of the curve, - o y: (number) y coordinate of the start of the curve - o }, - o end: { - o x: (number) x coordinate of the end of the curve, - o y: (number) y coordinate of the end of the curve - o }, - o alpha: (number) angle of the curve derivative at the point - o } - \*/ - Snap.path.findDotsAtSegment = findDotsAtSegment; - /*\ - * Snap.path.bezierBBox - [ method ] - ** - * Utility method - ** - * Returns the bounding box of a given cubic beziér curve - - p1x (number) x of the first point of the curve - - p1y (number) y of the first point of the curve - - c1x (number) x of the first anchor of the curve - - c1y (number) y of the first anchor of the curve - - c2x (number) x of the second anchor of the curve - - c2y (number) y of the second anchor of the curve - - p2x (number) x of the second point of the curve - - p2y (number) y of the second point of the curve - * or - - bez (array) array of six points for beziér curve - = (object) bounding box - o { - o x: (number) x coordinate of the left top point of the box, - o y: (number) y coordinate of the left top point of the box, - o x2: (number) x coordinate of the right bottom point of the box, - o y2: (number) y coordinate of the right bottom point of the box, - o width: (number) width of the box, - o height: (number) height of the box - o } - \*/ - Snap.path.bezierBBox = bezierBBox; - /*\ - * Snap.path.isPointInsideBBox - [ method ] - ** - * Utility method - ** - * Returns `true` if given point is inside bounding box - - bbox (string) bounding box - - x (string) x coordinate of the point - - y (string) y coordinate of the point - = (boolean) `true` if point is inside - \*/ - Snap.path.isPointInsideBBox = isPointInsideBBox; - Snap.closest = function (x, y, X, Y) { - var r = 100, - b = box(x - r / 2, y - r / 2, r, r), - inside = [], - getter = X[0].hasOwnProperty("x") ? function (i) { - return { - x: X[i].x, - y: X[i].y - }; - } : function (i) { - return { - x: X[i], - y: Y[i] - }; - }, - found = 0; - while (r <= 1e6 && !found) { - for (var i = 0, ii = X.length; i < ii; i++) { - var xy = getter(i); - if (isPointInsideBBox(b, xy.x, xy.y)) { - found++; - inside.push(xy); - break; - } - } - if (!found) { - r *= 2; - b = box(x - r / 2, y - r / 2, r, r) - } - } - if (r == 1e6) { - return; - } - var len = Infinity, - res; - for (i = 0, ii = inside.length; i < ii; i++) { - var l = Snap.len(x, y, inside[i].x, inside[i].y); - if (len > l) { - len = l; - inside[i].len = l; - res = inside[i]; - } - } - return res; - }; - /*\ - * Snap.path.isBBoxIntersect - [ method ] - ** - * Utility method - ** - * Returns `true` if two bounding boxes intersect - - bbox1 (string) first bounding box - - bbox2 (string) second bounding box - = (boolean) `true` if bounding boxes intersect - \*/ - Snap.path.isBBoxIntersect = isBBoxIntersect; - /*\ - * Snap.path.intersection - [ method ] - ** - * Utility method - ** - * Finds intersections of two paths - - path1 (string) path string - - path2 (string) path string - = (array) dots of intersection - o [ - o { - o x: (number) x coordinate of the point, - o y: (number) y coordinate of the point, - o t1: (number) t value for segment of path1, - o t2: (number) t value for segment of path2, - o segment1: (number) order number for segment of path1, - o segment2: (number) order number for segment of path2, - o bez1: (array) eight coordinates representing beziér curve for the segment of path1, - o bez2: (array) eight coordinates representing beziér curve for the segment of path2 - o } - o ] - \*/ - Snap.path.intersection = pathIntersection; - Snap.path.intersectionNumber = pathIntersectionNumber; - /*\ - * Snap.path.isPointInside - [ method ] - ** - * Utility method - ** - * Returns `true` if given point is inside a given closed path. - * - * Note: fill mode doesn’t affect the result of this method. - - path (string) path string - - x (number) x of the point - - y (number) y of the point - = (boolean) `true` if point is inside the path - \*/ - Snap.path.isPointInside = isPointInsidePath; - /*\ - * Snap.path.getBBox - [ method ] - ** - * Utility method - ** - * Returns the bounding box of a given path - - path (string) path string - = (object) bounding box - o { - o x: (number) x coordinate of the left top point of the box, - o y: (number) y coordinate of the left top point of the box, - o x2: (number) x coordinate of the right bottom point of the box, - o y2: (number) y coordinate of the right bottom point of the box, - o width: (number) width of the box, - o height: (number) height of the box - o } - \*/ - Snap.path.getBBox = pathBBox; - Snap.path.get = getPath; - /*\ - * Snap.path.toRelative - [ method ] - ** - * Utility method - ** - * Converts path coordinates into relative values - - path (string) path string - = (array) path string - \*/ - Snap.path.toRelative = pathToRelative; - /*\ - * Snap.path.toAbsolute - [ method ] - ** - * Utility method - ** - * Converts path coordinates into absolute values - - path (string) path string - = (array) path string - \*/ - Snap.path.toAbsolute = pathToAbsolute; - /*\ - * Snap.path.toCubic - [ method ] - ** - * Utility method - ** - * Converts path to a new path where all segments are cubic beziér curves - - pathString (string|array) path string or array of segments - = (array) array of segments - \*/ - Snap.path.toCubic = path2curve; - /*\ - * Snap.path.map - [ method ] - ** - * Transform the path string with the given matrix - - path (string) path string - - matrix (object) see @Matrix - = (string) transformed path string - \*/ - Snap.path.map = mapPath; - Snap.path.toString = toString; - Snap.path.clone = pathClone; - }); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob) { - var mmax = Math.max, - mmin = Math.min; - - // Set - var Set = function (items) { - this.items = []; - this.bindings = {}; - this.length = 0; - this.type = "set"; - if (items) { - for (var i = 0, ii = items.length; i < ii; i++) { - if (items[i]) { - this[this.items.length] = this.items[this.items.length] = items[i]; - this.length++; - } - } - } - }, - setproto = Set.prototype; - /*\ - * Set.push - [ method ] - ** - * Adds each argument to the current set - = (object) original element - \*/ - setproto.push = function () { - var item, - len; - for (var i = 0, ii = arguments.length; i < ii; i++) { - item = arguments[i]; - if (item) { - len = this.items.length; - this[len] = this.items[len] = item; - this.length++; - } - } - return this; - }; - /*\ - * Set.pop - [ method ] - ** - * Removes last element and returns it - = (object) element - \*/ - setproto.pop = function () { - this.length && delete this[this.length--]; - return this.items.pop(); - }; - /*\ - * Set.forEach - [ method ] - ** - * Executes given function for each element in the set - * - * If the function returns `false`, the loop stops running. - ** - - callback (function) function to run - - thisArg (object) context object for the callback - = (object) Set object - \*/ - setproto.forEach = function (callback, thisArg) { - for (var i = 0, ii = this.items.length; i < ii; i++) { - if (callback.call(thisArg, this.items[i], i) === false) { - return this; - } - } - return this; - }; - /*\ - * Set.animate - [ method ] - ** - * Animates each element in set in sync. - * - ** - - attrs (object) key-value pairs of destination attributes - - duration (number) duration of the animation in milliseconds - - easing (function) #optional easing function from @mina or custom - - callback (function) #optional callback function that executes when the animation ends - * or - - animation (array) array of animation parameter for each element in set in format `[attrs, duration, easing, callback]` - > Usage - | // animate all elements in set to radius 10 - | set.animate({r: 10}, 500, mina.easein); - | // or - | // animate first element to radius 10, but second to radius 20 and in different time - | set.animate([{r: 10}, 500, mina.easein], [{r: 20}, 1500, mina.easein]); - = (Element) the current element - \*/ - setproto.animate = function (attrs, ms, easing, callback) { - if (typeof easing == "function" && !easing.length) { - callback = easing; - easing = mina.linear; - } - if (attrs instanceof Snap._.Animation) { - callback = attrs.callback; - easing = attrs.easing; - ms = easing.dur; - attrs = attrs.attr; - } - var args = arguments; - if (Snap.is(attrs, "array") && Snap.is(args[args.length - 1], "array")) { - var each = true; - } - var begin, - handler = function () { - if (begin) { - this.b = begin; - } else { - begin = this.b; - } - }, - cb = 0, - set = this, - callbacker = callback && function () { - if (++cb == set.length) { - callback.call(this); - } - }; - return this.forEach(function (el, i) { - eve.once("snap.animcreated." + el.id, handler); - if (each) { - args[i] && el.animate.apply(el, args[i]); - } else { - el.animate(attrs, ms, easing, callbacker); - } - }); - }; - setproto.remove = function () { - while (this.length) { - this.pop().remove(); - } - return this; - }; - /*\ - * Set.bind - [ method ] - ** - * Specifies how to handle a specific attribute when applied - * to a set. - * - ** - - attr (string) attribute name - - callback (function) function to run - * or - - attr (string) attribute name - - element (Element) specific element in the set to apply the attribute to - * or - - attr (string) attribute name - - element (Element) specific element in the set to apply the attribute to - - eattr (string) attribute on the element to bind the attribute to - = (object) Set object - \*/ - setproto.bind = function (attr, a, b) { - var data = {}; - if (typeof a == "function") { - this.bindings[attr] = a; - } else { - var aname = b || attr; - this.bindings[attr] = function (v) { - data[aname] = v; - a.attr(data); - }; - } - return this; - }; - setproto.attr = function (value) { - var unbound = {}; - for (var k in value) { - if (this.bindings[k]) { - this.bindings[k](value[k]); - } else { - unbound[k] = value[k]; - } - } - for (var i = 0, ii = this.items.length; i < ii; i++) { - this.items[i].attr(unbound); - } - return this; - }; - /*\ - * Set.clear - [ method ] - ** - * Removes all elements from the set - \*/ - setproto.clear = function () { - while (this.length) { - this.pop(); - } - }; - /*\ - * Set.splice - [ method ] - ** - * Removes range of elements from the set - ** - - index (number) position of the deletion - - count (number) number of element to remove - - insertion… (object) #optional elements to insert - = (object) set elements that were deleted - \*/ - setproto.splice = function (index, count, insertion) { - index = index < 0 ? mmax(this.length + index, 0) : index; - count = mmax(0, mmin(this.length - index, count)); - var tail = [], - todel = [], - args = [], - i; - for (i = 2; i < arguments.length; i++) { - args.push(arguments[i]); - } - for (i = 0; i < count; i++) { - todel.push(this[index + i]); - } - for (; i < this.length - index; i++) { - tail.push(this[index + i]); - } - var arglen = args.length; - for (i = 0; i < arglen + tail.length; i++) { - this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen]; - } - i = this.items.length = this.length -= count - arglen; - while (this[i]) { - delete this[i++]; - } - return new Set(todel); - }; - /*\ - * Set.exclude - [ method ] - ** - * Removes given element from the set - ** - - element (object) element to remove - = (boolean) `true` if object was found and removed from the set - \*/ - setproto.exclude = function (el) { - for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) { - this.splice(i, 1); - return true; - } - return false; - }; - setproto.insertAfter = function (el) { - var i = this.items.length; - while (i--) { - this.items[i].insertAfter(el); - } - return this; - }; - setproto.getBBox = function () { - var x = [], - y = [], - x2 = [], - y2 = []; - for (var i = this.items.length; i--;) if (!this.items[i].removed) { - var box = this.items[i].getBBox(); - x.push(box.x); - y.push(box.y); - x2.push(box.x + box.width); - y2.push(box.y + box.height); - } - x = mmin.apply(0, x); - y = mmin.apply(0, y); - x2 = mmax.apply(0, x2); - y2 = mmax.apply(0, y2); - return { - x: x, - y: y, - x2: x2, - y2: y2, - width: x2 - x, - height: y2 - y, - cx: x + (x2 - x) / 2, - cy: y + (y2 - y) / 2 - }; - }; - setproto.clone = function (s) { - s = new Set; - for (var i = 0, ii = this.items.length; i < ii; i++) { - s.push(this.items[i].clone()); - } - return s; - }; - setproto.toString = function () { - return "Snap\u2018s set"; - }; - setproto.type = "set"; - // export - Snap.Set = Set; - Snap.set = function () { - var set = new Set; - if (arguments.length) { - set.push.apply(set, Array.prototype.slice.call(arguments, 0)); - } - return set; - }; - }); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob) { - var names = {}, - reUnit = /[a-z]+$/i, - Str = String; - names.stroke = names.fill = "colour"; - function getEmpty(item) { - var l = item[0]; - switch (l.toLowerCase()) { - case "t": return [l, 0, 0]; - case "m": return [l, 1, 0, 0, 1, 0, 0]; - case "r": if (item.length == 4) { - return [l, 0, item[2], item[3]]; - } else { - return [l, 0]; - } - case "s": if (item.length == 5) { - return [l, 1, 1, item[3], item[4]]; - } else if (item.length == 3) { - return [l, 1, 1]; - } else { - return [l, 1]; - } - } - } - function equaliseTransform(t1, t2, getBBox) { - t2 = Str(t2).replace(/\.{3}|\u2026/g, t1); - t1 = Snap.parseTransformString(t1) || []; - t2 = Snap.parseTransformString(t2) || []; - var maxlength = Math.max(t1.length, t2.length), - from = [], - to = [], - i = 0, j, jj, - tt1, tt2; - for (; i < maxlength; i++) { - tt1 = t1[i] || getEmpty(t2[i]); - tt2 = t2[i] || getEmpty(tt1); - if ((tt1[0] != tt2[0]) || - (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || - (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) - ) { - t1 = Snap._.transform2matrix(t1, getBBox()); - t2 = Snap._.transform2matrix(t2, getBBox()); - from = [["m", t1.a, t1.b, t1.c, t1.d, t1.e, t1.f]]; - to = [["m", t2.a, t2.b, t2.c, t2.d, t2.e, t2.f]]; - break; - } - from[i] = []; - to[i] = []; - for (j = 0, jj = Math.max(tt1.length, tt2.length); j < jj; j++) { - j in tt1 && (from[i][j] = tt1[j]); - j in tt2 && (to[i][j] = tt2[j]); - } - } - return { - from: path2array(from), - to: path2array(to), - f: getPath(from) - }; - } - function getNumber(val) { - return val; - } - function getUnit(unit) { - return function (val) { - return +val.toFixed(3) + unit; - }; - } - function getViewBox(val) { - return val.join(" "); - } - function getColour(clr) { - return Snap.rgb(clr[0], clr[1], clr[2]); - } - function getPath(path) { - var k = 0, i, ii, j, jj, out, a, b = []; - for (i = 0, ii = path.length; i < ii; i++) { - out = "["; - a = ['"' + path[i][0] + '"']; - for (j = 1, jj = path[i].length; j < jj; j++) { - a[j] = "val[" + (k++) + "]"; - } - out += a + "]"; - b[i] = out; - } - return Function("val", "return Snap.path.toString.call([" + b + "])"); - } - function path2array(path) { - var out = []; - for (var i = 0, ii = path.length; i < ii; i++) { - for (var j = 1, jj = path[i].length; j < jj; j++) { - out.push(path[i][j]); - } - } - return out; - } - function isNumeric(obj) { - return isFinite(parseFloat(obj)); - } - function arrayEqual(arr1, arr2) { - if (!Snap.is(arr1, "array") || !Snap.is(arr2, "array")) { - return false; - } - return arr1.toString() == arr2.toString(); - } - Element.prototype.equal = function (name, b) { - return eve("snap.util.equal", this, name, b).firstDefined(); - }; - eve.on("snap.util.equal", function (name, b) { - var A, B, a = Str(this.attr(name) || ""), - el = this; - if (isNumeric(a) && isNumeric(b)) { - return { - from: parseFloat(a), - to: parseFloat(b), - f: getNumber - }; - } - if (names[name] == "colour") { - A = Snap.color(a); - B = Snap.color(b); - return { - from: [A.r, A.g, A.b, A.opacity], - to: [B.r, B.g, B.b, B.opacity], - f: getColour - }; - } - if (name == "viewBox") { - A = this.attr(name).vb.split(" ").map(Number); - B = b.split(" ").map(Number); - return { - from: A, - to: B, - f: getViewBox - }; - } - if (name == "transform" || name == "gradientTransform" || name == "patternTransform") { - if (b instanceof Snap.Matrix) { - b = b.toTransformString(); - } - if (!Snap._.rgTransform.test(b)) { - b = Snap._.svgTransform2string(b); - } - return equaliseTransform(a, b, function () { - return el.getBBox(1); - }); - } - if (name == "d" || name == "path") { - A = Snap.path.toCubic(a, b); - return { - from: path2array(A[0]), - to: path2array(A[1]), - f: getPath(A[0]) - }; - } - if (name == "points") { - A = Str(a).split(Snap._.separator); - B = Str(b).split(Snap._.separator); - return { - from: A, - to: B, - f: function (val) { return val; } - }; - } - var aUnit = a.match(reUnit), - bUnit = Str(b).match(reUnit); - if (aUnit && arrayEqual(aUnit, bUnit)) { - return { - from: parseFloat(a), - to: parseFloat(b), - f: getUnit(aUnit) - }; - } else { - return { - from: this.asPX(name), - to: this.asPX(name, b), - f: getNumber - }; - } - }); - }); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob) { - var elproto = Element.prototype, - has = "hasOwnProperty", - supportsTouch = "createTouch" in glob.doc, - events = [ - "click", "dblclick", "mousedown", "mousemove", "mouseout", - "mouseover", "mouseup", "touchstart", "touchmove", "touchend", - "touchcancel" - ], - touchMap = { - mousedown: "touchstart", - mousemove: "touchmove", - mouseup: "touchend" - }, - getScroll = function (xy, el) { - var name = xy == "y" ? "scrollTop" : "scrollLeft", - doc = el && el.node ? el.node.ownerDocument : glob.doc; - return doc[name in doc.documentElement ? "documentElement" : "body"][name]; - }, - preventDefault = function () { - this.returnValue = false; - }, - preventTouch = function () { - return this.originalEvent.preventDefault(); - }, - stopPropagation = function () { - this.cancelBubble = true; - }, - stopTouch = function () { - return this.originalEvent.stopPropagation(); - }, - addEvent = function (obj, type, fn, element) { - var realName = supportsTouch && touchMap[type] ? touchMap[type] : type, - f = function (e) { - var scrollY = getScroll("y", element), - scrollX = getScroll("x", element); - if (supportsTouch && touchMap[has](type)) { - for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { - if (e.targetTouches[i].target == obj || obj.contains(e.targetTouches[i].target)) { - var olde = e; - e = e.targetTouches[i]; - e.originalEvent = olde; - e.preventDefault = preventTouch; - e.stopPropagation = stopTouch; - break; - } - } - } - var x = e.clientX + scrollX, - y = e.clientY + scrollY; - return fn.call(element, e, x, y); - }; - - if (type !== realName) { - obj.addEventListener(type, f, false); - } - - obj.addEventListener(realName, f, false); - - return function () { - if (type !== realName) { - obj.removeEventListener(type, f, false); - } - - obj.removeEventListener(realName, f, false); - return true; - }; - }, - drag = [], - dragMove = function (e) { - var x = e.clientX, - y = e.clientY, - scrollY = getScroll("y"), - scrollX = getScroll("x"), - dragi, - j = drag.length; - while (j--) { - dragi = drag[j]; - if (supportsTouch) { - var i = e.touches && e.touches.length, - touch; - while (i--) { - touch = e.touches[i]; - if (touch.identifier == dragi.el._drag.id || dragi.el.node.contains(touch.target)) { - x = touch.clientX; - y = touch.clientY; - (e.originalEvent ? e.originalEvent : e).preventDefault(); - break; - } - } - } else { - e.preventDefault(); - } - var node = dragi.el.node, - o, - next = node.nextSibling, - parent = node.parentNode, - display = node.style.display; - // glob.win.opera && parent.removeChild(node); - // node.style.display = "none"; - // o = dragi.el.paper.getElementByPoint(x, y); - // node.style.display = display; - // glob.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node)); - // o && eve("snap.drag.over." + dragi.el.id, dragi.el, o); - x += scrollX; - y += scrollY; - eve("snap.drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e); - } - }, - dragUp = function (e) { - Snap.unmousemove(dragMove).unmouseup(dragUp); - var i = drag.length, - dragi; - while (i--) { - dragi = drag[i]; - dragi.el._drag = {}; - eve("snap.drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e); - eve.off("snap.drag.*." + dragi.el.id); - } - drag = []; - }; - /*\ - * Element.click - [ method ] - ** - * Adds a click event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.unclick - [ method ] - ** - * Removes a click event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.dblclick - [ method ] - ** - * Adds a double click event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.undblclick - [ method ] - ** - * Removes a double click event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.mousedown - [ method ] - ** - * Adds a mousedown event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.unmousedown - [ method ] - ** - * Removes a mousedown event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.mousemove - [ method ] - ** - * Adds a mousemove event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.unmousemove - [ method ] - ** - * Removes a mousemove event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.mouseout - [ method ] - ** - * Adds a mouseout event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.unmouseout - [ method ] - ** - * Removes a mouseout event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.mouseover - [ method ] - ** - * Adds a mouseover event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.unmouseover - [ method ] - ** - * Removes a mouseover event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.mouseup - [ method ] - ** - * Adds a mouseup event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.unmouseup - [ method ] - ** - * Removes a mouseup event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.touchstart - [ method ] - ** - * Adds a touchstart event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.untouchstart - [ method ] - ** - * Removes a touchstart event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.touchmove - [ method ] - ** - * Adds a touchmove event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.untouchmove - [ method ] - ** - * Removes a touchmove event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.touchend - [ method ] - ** - * Adds a touchend event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.untouchend - [ method ] - ** - * Removes a touchend event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - - /*\ - * Element.touchcancel - [ method ] - ** - * Adds a touchcancel event handler to the element - - handler (function) handler for the event - = (object) @Element - \*/ - /*\ - * Element.untouchcancel - [ method ] - ** - * Removes a touchcancel event handler from the element - - handler (function) handler for the event - = (object) @Element - \*/ - for (var i = events.length; i--;) { - (function (eventName) { - Snap[eventName] = elproto[eventName] = function (fn, scope) { - if (Snap.is(fn, "function")) { - this.events = this.events || []; - this.events.push({ - name: eventName, - f: fn, - unbind: addEvent(this.node || document, eventName, fn, scope || this) - }); - } else { - for (var i = 0, ii = this.events.length; i < ii; i++) if (this.events[i].name == eventName) { - try { - this.events[i].f.call(this); - } catch (e) {} - } - } - return this; - }; - Snap["un" + eventName] = - elproto["un" + eventName] = function (fn) { - var events = this.events || [], - l = events.length; - while (l--) if (events[l].name == eventName && - (events[l].f == fn || !fn)) { - events[l].unbind(); - events.splice(l, 1); - !events.length && delete this.events; - return this; - } - return this; - }; - })(events[i]); - } - /*\ - * Element.hover - [ method ] - ** - * Adds hover event handlers to the element - - f_in (function) handler for hover in - - f_out (function) handler for hover out - - icontext (object) #optional context for hover in handler - - ocontext (object) #optional context for hover out handler - = (object) @Element - \*/ - elproto.hover = function (f_in, f_out, scope_in, scope_out) { - return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in); - }; - /*\ - * Element.unhover - [ method ] - ** - * Removes hover event handlers from the element - - f_in (function) handler for hover in - - f_out (function) handler for hover out - = (object) @Element - \*/ - elproto.unhover = function (f_in, f_out) { - return this.unmouseover(f_in).unmouseout(f_out); - }; - var draggable = []; - // SIERRA unclear what _context_ refers to for starting, ending, moving the drag gesture. - // SIERRA Element.drag(): _x position of the mouse_: Where are the x/y values offset from? - // SIERRA Element.drag(): much of this member's doc appears to be duplicated for some reason. - // SIERRA Unclear about this sentence: _Additionally following drag events will be triggered: drag.start. on start, drag.end. on end and drag.move. on every move._ Is there a global _drag_ object to which you can assign handlers keyed by an element's ID? - /*\ - * Element.drag - [ method ] - ** - * Adds event handlers for an element's drag gesture - ** - - onmove (function) handler for moving - - onstart (function) handler for drag start - - onend (function) handler for drag end - - mcontext (object) #optional context for moving handler - - scontext (object) #optional context for drag start handler - - econtext (object) #optional context for drag end handler - * Additionaly following `drag` events are triggered: `drag.start.` on start, - * `drag.end.` on end and `drag.move.` on every move. When element is dragged over another element - * `drag.over.` fires as well. - * - * Start event and start handler are called in specified context or in context of the element with following parameters: - o x (number) x position of the mouse - o y (number) y position of the mouse - o event (object) DOM event object - * Move event and move handler are called in specified context or in context of the element with following parameters: - o dx (number) shift by x from the start point - o dy (number) shift by y from the start point - o x (number) x position of the mouse - o y (number) y position of the mouse - o event (object) DOM event object - * End event and end handler are called in specified context or in context of the element with following parameters: - o event (object) DOM event object - = (object) @Element - \*/ - elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) { - var el = this; - if (!arguments.length) { - var origTransform; - return el.drag(function (dx, dy) { - this.attr({ - transform: origTransform + (origTransform ? "T" : "t") + [dx, dy] - }); - }, function () { - origTransform = this.transform().local; - }); - } - function start(e, x, y) { - (e.originalEvent || e).preventDefault(); - el._drag.x = x; - el._drag.y = y; - el._drag.id = e.identifier; - !drag.length && Snap.mousemove(dragMove).mouseup(dragUp); - drag.push({el: el, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope}); - onstart && eve.on("snap.drag.start." + el.id, onstart); - onmove && eve.on("snap.drag.move." + el.id, onmove); - onend && eve.on("snap.drag.end." + el.id, onend); - eve("snap.drag.start." + el.id, start_scope || move_scope || el, x, y, e); - } - function init(e, x, y) { - eve("snap.draginit." + el.id, el, e, x, y); - } - eve.on("snap.draginit." + el.id, start); - el._drag = {}; - draggable.push({el: el, start: start, init: init}); - el.mousedown(init); - return el; - }; - /* - * Element.onDragOver - [ method ] - ** - * Shortcut to assign event handler for `drag.over.` event, where `id` is the element's `id` (see @Element.id) - - f (function) handler for event, first argument would be the element you are dragging over - \*/ - // elproto.onDragOver = function (f) { - // f ? eve.on("snap.drag.over." + this.id, f) : eve.unbind("snap.drag.over." + this.id); - // }; - /*\ - * Element.undrag - [ method ] - ** - * Removes all drag event handlers from the given element - \*/ - elproto.undrag = function () { - var i = draggable.length; - while (i--) if (draggable[i].el == this) { - this.unmousedown(draggable[i].init); - draggable.splice(i, 1); - eve.unbind("snap.drag.*." + this.id); - eve.unbind("snap.draginit." + this.id); - } - !draggable.length && Snap.unmousemove(dragMove).unmouseup(dragUp); - return this; - }; - }); - - // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob) { - var elproto = Element.prototype, - pproto = Paper.prototype, - rgurl = /^\s*url\((.+)\)/, - Str = String, - $ = Snap._.$; - Snap.filter = {}; - /*\ - * Paper.filter - [ method ] - ** - * Creates a `` element - ** - - filstr (string) SVG fragment of filter provided as a string - = (object) @Element - * Note: It is recommended to use filters embedded into the page inside an empty SVG element. - > Usage - | var f = paper.filter(''), - | c = paper.circle(10, 10, 10).attr({ - | filter: f - | }); - \*/ - pproto.filter = function (filstr) { - var paper = this; - if (paper.type != "svg") { - paper = paper.paper; - } - var f = Snap.parse(Str(filstr)), - id = Snap._.id(), - width = paper.node.offsetWidth, - height = paper.node.offsetHeight, - filter = $("filter"); - $(filter, { - id: id, - filterUnits: "userSpaceOnUse" - }); - filter.appendChild(f.node); - paper.defs.appendChild(filter); - return new Element(filter); - }; - - eve.on("snap.util.getattr.filter", function () { - eve.stop(); - var p = $(this.node, "filter"); - if (p) { - var match = Str(p).match(rgurl); - return match && Snap.select(match[1]); - } - }); - eve.on("snap.util.attr.filter", function (value) { - if (value instanceof Element && value.type == "filter") { - eve.stop(); - var id = value.node.id; - if (!id) { - $(value.node, {id: value.id}); - id = value.id; - } - $(this.node, { - filter: Snap.url(id) - }); - } - if (!value || value == "none") { - eve.stop(); - this.node.removeAttribute("filter"); - } - }); - /*\ - * Snap.filter.blur - [ method ] - ** - * Returns an SVG markup string for the blur filter - ** - - x (number) amount of horizontal blur, in pixels - - y (number) #optional amount of vertical blur, in pixels - = (string) filter representation - > Usage - | var f = paper.filter(Snap.filter.blur(5, 10)), - | c = paper.circle(10, 10, 10).attr({ - | filter: f - | }); - \*/ - Snap.filter.blur = function (x, y) { - if (x == null) { - x = 2; - } - var def = y == null ? x : [x, y]; - return Snap.format('\', { - def: def - }); - }; - Snap.filter.blur.toString = function () { - return this(); - }; - /*\ - * Snap.filter.shadow - [ method ] - ** - * Returns an SVG markup string for the shadow filter - ** - - dx (number) #optional horizontal shift of the shadow, in pixels - - dy (number) #optional vertical shift of the shadow, in pixels - - blur (number) #optional amount of blur - - color (string) #optional color of the shadow - - opacity (number) #optional `0..1` opacity of the shadow - * or - - dx (number) #optional horizontal shift of the shadow, in pixels - - dy (number) #optional vertical shift of the shadow, in pixels - - color (string) #optional color of the shadow - - opacity (number) #optional `0..1` opacity of the shadow - * which makes blur default to `4`. Or - - dx (number) #optional horizontal shift of the shadow, in pixels - - dy (number) #optional vertical shift of the shadow, in pixels - - opacity (number) #optional `0..1` opacity of the shadow - = (string) filter representation - > Usage - | var f = paper.filter(Snap.filter.shadow(0, 2, 3)), - | c = paper.circle(10, 10, 10).attr({ - | filter: f - | }); - \*/ - Snap.filter.shadow = function (dx, dy, blur, color, opacity) { - if (typeof blur == "string") { - color = blur; - opacity = color; - blur = 4; - } - if (typeof color != "string") { - opacity = color; - color = "#000"; - } - color = color || "#000"; - if (blur == null) { - blur = 4; - } - if (opacity == null) { - opacity = 1; - } - if (dx == null) { - dx = 0; - dy = 2; - } - if (dy == null) { - dy = dx; - } - color = Snap.color(color); - return Snap.format('', { - color: color, - dx: dx, - dy: dy, - blur: blur, - opacity: opacity - }); - }; - Snap.filter.shadow.toString = function () { - return this(); - }; - /*\ - * Snap.filter.grayscale - [ method ] - ** - * Returns an SVG markup string for the grayscale filter - ** - - amount (number) amount of filter (`0..1`) - = (string) filter representation - \*/ - Snap.filter.grayscale = function (amount) { - if (amount == null) { - amount = 1; - } - return Snap.format('', { - a: 0.2126 + 0.7874 * (1 - amount), - b: 0.7152 - 0.7152 * (1 - amount), - c: 0.0722 - 0.0722 * (1 - amount), - d: 0.2126 - 0.2126 * (1 - amount), - e: 0.7152 + 0.2848 * (1 - amount), - f: 0.0722 - 0.0722 * (1 - amount), - g: 0.2126 - 0.2126 * (1 - amount), - h: 0.0722 + 0.9278 * (1 - amount) - }); - }; - Snap.filter.grayscale.toString = function () { - return this(); - }; - /*\ - * Snap.filter.sepia - [ method ] - ** - * Returns an SVG markup string for the sepia filter - ** - - amount (number) amount of filter (`0..1`) - = (string) filter representation - \*/ - Snap.filter.sepia = function (amount) { - if (amount == null) { - amount = 1; - } - return Snap.format('', { - a: 0.393 + 0.607 * (1 - amount), - b: 0.769 - 0.769 * (1 - amount), - c: 0.189 - 0.189 * (1 - amount), - d: 0.349 - 0.349 * (1 - amount), - e: 0.686 + 0.314 * (1 - amount), - f: 0.168 - 0.168 * (1 - amount), - g: 0.272 - 0.272 * (1 - amount), - h: 0.534 - 0.534 * (1 - amount), - i: 0.131 + 0.869 * (1 - amount) - }); - }; - Snap.filter.sepia.toString = function () { - return this(); - }; - /*\ - * Snap.filter.saturate - [ method ] - ** - * Returns an SVG markup string for the saturate filter - ** - - amount (number) amount of filter (`0..1`) - = (string) filter representation - \*/ - Snap.filter.saturate = function (amount) { - if (amount == null) { - amount = 1; - } - return Snap.format('', { - amount: 1 - amount - }); - }; - Snap.filter.saturate.toString = function () { - return this(); - }; - /*\ - * Snap.filter.hueRotate - [ method ] - ** - * Returns an SVG markup string for the hue-rotate filter - ** - - angle (number) angle of rotation - = (string) filter representation - \*/ - Snap.filter.hueRotate = function (angle) { - angle = angle || 0; - return Snap.format('', { - angle: angle - }); - }; - Snap.filter.hueRotate.toString = function () { - return this(); - }; - /*\ - * Snap.filter.invert - [ method ] - ** - * Returns an SVG markup string for the invert filter - ** - - amount (number) amount of filter (`0..1`) - = (string) filter representation - \*/ - Snap.filter.invert = function (amount) { - if (amount == null) { - amount = 1; - } - // - return Snap.format('', { - amount: amount, - amount2: 1 - amount - }); - }; - Snap.filter.invert.toString = function () { - return this(); - }; - /*\ - * Snap.filter.brightness - [ method ] - ** - * Returns an SVG markup string for the brightness filter - ** - - amount (number) amount of filter (`0..1`) - = (string) filter representation - \*/ - Snap.filter.brightness = function (amount) { - if (amount == null) { - amount = 1; - } - return Snap.format('', { - amount: amount - }); - }; - Snap.filter.brightness.toString = function () { - return this(); - }; - /*\ - * Snap.filter.contrast - [ method ] - ** - * Returns an SVG markup string for the contrast filter - ** - - amount (number) amount of filter (`0..1`) - = (string) filter representation - \*/ - Snap.filter.contrast = function (amount) { - if (amount == null) { - amount = 1; - } - return Snap.format('', { - amount: amount, - amount2: .5 - amount / 2 - }); - }; - Snap.filter.contrast.toString = function () { - return this(); - }; - }); - - // Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved. - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - Snap.plugin(function (Snap, Element, Paper, glob, Fragment) { - var box = Snap._.box, - is = Snap.is, - firstLetter = /^[^a-z]*([tbmlrc])/i, - toString = function () { - return "T" + this.dx + "," + this.dy; - }; - /*\ - * Element.getAlign - [ method ] - ** - * Returns shift needed to align the element relatively to given element. - * If no elements specified, parent `` container will be used. - - el (object) @optional alignment element - - way (string) one of six values: `"top"`, `"middle"`, `"bottom"`, `"left"`, `"center"`, `"right"` - = (object|string) Object in format `{dx: , dy: }` also has a string representation as a transformation string - > Usage - | el.transform(el.getAlign(el2, "top")); - * or - | var dy = el.getAlign(el2, "top").dy; - \*/ - Element.prototype.getAlign = function (el, way) { - if (way == null && is(el, "string")) { - way = el; - el = null; - } - el = el || this.paper; - var bx = el.getBBox ? el.getBBox() : box(el), - bb = this.getBBox(), - out = {}; - way = way && way.match(firstLetter); - way = way ? way[1].toLowerCase() : "c"; - switch (way) { - case "t": - out.dx = 0; - out.dy = bx.y - bb.y; - break; - case "b": - out.dx = 0; - out.dy = bx.y2 - bb.y2; - break; - case "m": - out.dx = 0; - out.dy = bx.cy - bb.cy; - break; - case "l": - out.dx = bx.x - bb.x; - out.dy = 0; - break; - case "r": - out.dx = bx.x2 - bb.x2; - out.dy = 0; - break; - default: - out.dx = bx.cx - bb.cx; - out.dy = 0; - break; - } - out.toString = toString; - return out; - }; - /*\ - * Element.align - [ method ] - ** - * Aligns the element relatively to given one via transformation. - * If no elements specified, parent `` container will be used. - - el (object) @optional alignment element - - way (string) one of six values: `"top"`, `"middle"`, `"bottom"`, `"left"`, `"center"`, `"right"` - = (object) this element - > Usage - | el.align(el2, "top"); - * or - | el.align("middle"); - \*/ - Element.prototype.align = function (el, way) { - return this.transform("..." + this.getAlign(el, way)); - }; - }); - - return Snap; - })); - }.call(window)); - -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - /* Enabling us to resize a shape width a handler - #http://stackoverflow.com/questions/32390028/how-to-drag-and-resize-svg-rectangle-using-cursor-types - */ - eventEmitter = __webpack_require__(4)({}); - - var ShapeResizer = function (paper, shape) { - this.paper = paper; - this.shape = shape; - this.handlers = []; - this.isResizing = false; - this.currentPosition = {}; - this.HANDLER_SIZE = 8; - this.SHAPE_MIN_SIZE = 20; - this.states = {}; - this.noop = function (){} - this.init(); - } - - var api = ShapeResizer.prototype = { - - init: function () { - this.showHandlers(); - }, - - showHandlers: function () { - /* show handler here */ - var bbox = this.shape.getBBox(); - var handleX = bbox.x - this.HANDLER_SIZE/2; - var handleY = bbox.y - this.HANDLER_SIZE/2; - handler = this.paper.rect(handleX, handleY, this.HANDLER_SIZE, this.HANDLER_SIZE).attr({fill: 'red'}); - var handlerInfos = {position: "t_r", handler: handler}; - this.handlers.push(handlerInfos); - this.shapesGroup = this.paper.g(this.shape, handler); - this.attachEvents(); - }, - - /*one handlers */ - updateShapePositions: function (handlerData, dx, dy) { - //start - var handlerBBox = handlerData.handler.getBBox(); - var shapeBBox = this.shape.data("origBbox"); - var newX = handlerBBox.x + this.HANDLER_SIZE / 2; - var newY = handlerBBox.y + this.HANDLER_SIZE / 2; - - /*to the right => reduce the size */ - var newWidth = (dx > 0) ? shapeBBox.width - dx : shapeBBox.width + Math.abs(dx); - var newHeight = (dy > 0) ? shapeBBox.height - dy : shapeBBox.height + Math.abs(dy); - var transformValue = this.shape.data('origTransform') + (this.shape.data('origTransform') ? "T" : "t") + [dx, dy]; - this.shape.attr({'transform': transformValue, width: newWidth, height: newHeight}); - }, - - dragEvents: { - onStart: function (handlerData, dx, dy, e) { - this.startPosition = {x: e.clientX, y: e.clientY}; - this.isResizing = true; - this.currentPosition = {}; - handlerData.handler.data("origTransform", handlerData.handler.transform().local); - this.shape.data("origBbox", this.shape.getBBox()); - this.shape.data("origTransform", this.shape.transform().local); - }, - - onMove: function (handlerData, dx, dy, x, y, e) { - var transformValue = handlerData.handler.data('origTransform') + (handlerData.handler.data('origTransform') ? "T" : "t") + [dx, dy]; - this.currentPosition.x = e.clientX; - this.currentPosition.y = e.clientY; - /* deal with boundaries */ - if (! this.checkBondaries(dx, dy)) { return; } - handlerData.handler.attr({ transform: transformValue}); - this.updateShapePositions(handlerData, dx, dy); - }, - - onStop: function () { - this.isResizing = false; - this.startPosition = {}; - this.currentPosition = {}; - } - }, - - checkBondaries: function (dx, dy) { - var result = true; - - if (this.shape.data("origBbox").width - dx <= this.SHAPE_MIN_SIZE) { - result = false; - } - - if (this.shape.data("origBbox").height - dy <= this.SHAPE_MIN_SIZE) { - result = false; - } - - return result; - }, - - destroy: function () { - this.handlers.map(function (handlerData) { - handlerData.handler.remove(); - }); - delete this; - }, - - attachEvents: function () { - var self = this; - this.handlers.map(function (handlerData) { - handlerData.handler.drag( - self.dragEvents.onMove.bind(self, handlerData), - self.dragEvents.onStart.bind(self, handlerData), - self.dragEvents.onStop.bind(self, handlerData)); - }); - - eventEmitter.on("cutout:clear", function () { - self.destroy(); - }); - - this.shapesGroup.drag(function (dx, dy) { - if (self.isResizing) { return; } - var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]; - this.transform(transformValue); - }, function () { - this.data('origTransform', this.transform().local); - }, this.noop); - }, - } - - module.exports = { - - apply_resize : function (paper, rect) { - new ShapeResizer(paper, rect); - } - } - -/***/ }, -/* 4 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var d = __webpack_require__(5) - , callable = __webpack_require__(18) - - , apply = Function.prototype.apply, call = Function.prototype.call - , create = Object.create, defineProperty = Object.defineProperty - , defineProperties = Object.defineProperties - , hasOwnProperty = Object.prototype.hasOwnProperty - , descriptor = { configurable: true, enumerable: false, writable: true } - - , on, once, off, emit, methods, descriptors, base; - - on = function (type, listener) { - var data; - - callable(listener); - - if (!hasOwnProperty.call(this, '__ee__')) { - data = descriptor.value = create(null); - defineProperty(this, '__ee__', descriptor); - descriptor.value = null; - } else { - data = this.__ee__; - } - if (!data[type]) data[type] = listener; - else if (typeof data[type] === 'object') data[type].push(listener); - else data[type] = [data[type], listener]; - - return this; - }; - - once = function (type, listener) { - var once, self; - - callable(listener); - self = this; - on.call(this, type, once = function () { - off.call(self, type, once); - apply.call(listener, this, arguments); - }); - - once.__eeOnceListener__ = listener; - return this; - }; - - off = function (type, listener) { - var data, listeners, candidate, i; - - callable(listener); - - if (!hasOwnProperty.call(this, '__ee__')) return this; - data = this.__ee__; - if (!data[type]) return this; - listeners = data[type]; - - if (typeof listeners === 'object') { - for (i = 0; (candidate = listeners[i]); ++i) { - if ((candidate === listener) || - (candidate.__eeOnceListener__ === listener)) { - if (listeners.length === 2) data[type] = listeners[i ? 0 : 1]; - else listeners.splice(i, 1); - } - } - } else { - if ((listeners === listener) || - (listeners.__eeOnceListener__ === listener)) { - delete data[type]; - } - } - - return this; - }; - - emit = function (type) { - var i, l, listener, listeners, args; - - if (!hasOwnProperty.call(this, '__ee__')) return; - listeners = this.__ee__[type]; - if (!listeners) return; - - if (typeof listeners === 'object') { - l = arguments.length; - args = new Array(l - 1); - for (i = 1; i < l; ++i) args[i - 1] = arguments[i]; - - listeners = listeners.slice(); - for (i = 0; (listener = listeners[i]); ++i) { - apply.call(listener, this, args); - } - } else { - switch (arguments.length) { - case 1: - call.call(listeners, this); - break; - case 2: - call.call(listeners, this, arguments[1]); - break; - case 3: - call.call(listeners, this, arguments[1], arguments[2]); - break; - default: - l = arguments.length; - args = new Array(l - 1); - for (i = 1; i < l; ++i) { - args[i - 1] = arguments[i]; - } - apply.call(listeners, this, args); - } - } - }; - - methods = { - on: on, - once: once, - off: off, - emit: emit - }; - - descriptors = { - on: d(on), - once: d(once), - off: d(off), - emit: d(emit) - }; - - base = defineProperties({}, descriptors); - - module.exports = exports = function (o) { - return (o == null) ? create(base) : defineProperties(Object(o), descriptors); - }; - exports.methods = methods; - - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var assign = __webpack_require__(6) - , normalizeOpts = __webpack_require__(13) - , isCallable = __webpack_require__(14) - , contains = __webpack_require__(15) - - , d; - - d = module.exports = function (dscr, value/*, options*/) { - var c, e, w, options, desc; - if ((arguments.length < 2) || (typeof dscr !== 'string')) { - options = value; - value = dscr; - dscr = null; - } else { - options = arguments[2]; - } - if (dscr == null) { - c = w = true; - e = false; - } else { - c = contains.call(dscr, 'c'); - e = contains.call(dscr, 'e'); - w = contains.call(dscr, 'w'); - } - - desc = { value: value, configurable: c, enumerable: e, writable: w }; - return !options ? desc : assign(normalizeOpts(options), desc); - }; - - d.gs = function (dscr, get, set/*, options*/) { - var c, e, options, desc; - if (typeof dscr !== 'string') { - options = set; - set = get; - get = dscr; - dscr = null; - } else { - options = arguments[3]; - } - if (get == null) { - get = undefined; - } else if (!isCallable(get)) { - options = get; - get = set = undefined; - } else if (set == null) { - set = undefined; - } else if (!isCallable(set)) { - options = set; - set = undefined; - } - if (dscr == null) { - c = true; - e = false; - } else { - c = contains.call(dscr, 'c'); - e = contains.call(dscr, 'e'); - } - - desc = { get: get, set: set, configurable: c, enumerable: e }; - return !options ? desc : assign(normalizeOpts(options), desc); - }; - - -/***/ }, -/* 6 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - module.exports = __webpack_require__(7)() - ? Object.assign - : __webpack_require__(8); - - -/***/ }, -/* 7 */ -/***/ function(module, exports) { - - 'use strict'; - - module.exports = function () { - var assign = Object.assign, obj; - if (typeof assign !== 'function') return false; - obj = { foo: 'raz' }; - assign(obj, { bar: 'dwa' }, { trzy: 'trzy' }); - return (obj.foo + obj.bar + obj.trzy) === 'razdwatrzy'; - }; - - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var keys = __webpack_require__(9) - , value = __webpack_require__(12) - - , max = Math.max; - - module.exports = function (dest, src/*, …srcn*/) { - var error, i, l = max(arguments.length, 2), assign; - dest = Object(value(dest)); - assign = function (key) { - try { dest[key] = src[key]; } catch (e) { - if (!error) error = e; - } - }; - for (i = 1; i < l; ++i) { - src = arguments[i]; - keys(src).forEach(assign); - } - if (error !== undefined) throw error; - return dest; - }; - - -/***/ }, -/* 9 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - module.exports = __webpack_require__(10)() - ? Object.keys - : __webpack_require__(11); - - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - 'use strict'; - - module.exports = function () { - try { - Object.keys('primitive'); - return true; - } catch (e) { return false; } - }; - - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - 'use strict'; - - var keys = Object.keys; - - module.exports = function (object) { - return keys(object == null ? object : Object(object)); - }; - - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - 'use strict'; - - module.exports = function (value) { - if (value == null) throw new TypeError("Cannot use null or undefined"); - return value; - }; - - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - 'use strict'; - - var forEach = Array.prototype.forEach, create = Object.create; - - var process = function (src, obj) { - var key; - for (key in src) obj[key] = src[key]; - }; - - module.exports = function (options/*, …options*/) { - var result = create(null); - forEach.call(arguments, function (options) { - if (options == null) return; - process(Object(options), result); - }); - return result; - }; - - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - // Deprecated - - 'use strict'; - - module.exports = function (obj) { return typeof obj === 'function'; }; - - -/***/ }, -/* 15 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - module.exports = __webpack_require__(16)() - ? String.prototype.contains - : __webpack_require__(17); - - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - 'use strict'; - - var str = 'razdwatrzy'; - - module.exports = function () { - if (typeof str.contains !== 'function') return false; - return ((str.contains('dwa') === true) && (str.contains('foo') === false)); - }; - - -/***/ }, -/* 17 */ -/***/ function(module, exports) { - - 'use strict'; - - var indexOf = String.prototype.indexOf; - - module.exports = function (searchString/*, position*/) { - return indexOf.call(this, searchString, arguments[1]) > -1; - }; - - -/***/ }, -/* 18 */ -/***/ function(module, exports) { - - 'use strict'; - - module.exports = function (fn) { - if (typeof fn !== 'function') throw new TypeError(fn + " is not a function"); - return fn; - }; - - -/***/ }, -/* 19 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {module.exports = global["jQuery"] = __webpack_require__(20); - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! - * jQuery JavaScript Library v2.2.4 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2016-05-20T17:23Z - */ - - (function( global, factory ) { - - if ( typeof module === "object" && typeof module.exports === "object" ) { - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - - // Pass this if window is not defined yet - }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - - // Support: Firefox 18+ - // Can't be in strict mode, several libs including ASP.NET trace - // the stack via arguments.caller.callee and Firefox dies if - // you try to trace through "use strict" call chains. (#13335) - //"use strict"; - var arr = []; - - var document = window.document; - - var slice = arr.slice; - - var concat = arr.concat; - - var push = arr.push; - - var indexOf = arr.indexOf; - - var class2type = {}; - - var toString = class2type.toString; - - var hasOwn = class2type.hasOwnProperty; - - var support = {}; - - - - var - version = "2.2.4", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android<4.1 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; - - jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // Start with an empty selector - selector: "", - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? - - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - - // Return all the elements in a clean array - slice.call( this ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice - }; - - jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = jQuery.isArray( copy ) ) ) ) { - - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray( src ) ? src : []; - - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; - }; - - jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isFunction: function( obj ) { - return jQuery.type( obj ) === "function"; - }, - - isArray: Array.isArray, - - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, - - isNumeric: function( obj ) { - - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - // adding 1 corrects loss of precision from parseFloat (#15100) - var realStringObj = obj && obj.toString(); - return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0; - }, - - isPlainObject: function( obj ) { - var key; - - // Not plain objects: - // - Any object or value whose internal [[Class]] property is not "[object Object]" - // - DOM nodes - // - window - if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call( obj, "constructor" ) && - !hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) { - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android<4.0, iOS<6 (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - var script, - indirect = eval; - - code = jQuery.trim( code ); - - if ( code ) { - - // If the code includes a valid, prologue position - // strict mode pragma, execute code by injecting a - // script tag into the document. - if ( code.indexOf( "use strict" ) === 1 ) { - script = document.createElement( "script" ); - script.text = code; - document.head.appendChild( script ).parentNode.removeChild( script ); - } else { - - // Otherwise, avoid the DOM node creation, insertion - // and removal by using an indirect global eval - - indirect( code ); - } - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Support: IE9-11+ - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // Support: Android<4.1 - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: Date.now, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support - } ); - - // JSHint would error on this code due to the Symbol not being defined in ES5. - // Defining this global in .jshintrc would create a danger of using the global - // unguarded in another place, it seems safer to just disable JSHint for these - // three lines. - /* jshint ignore: start */ - if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; - } - /* jshint ignore: end */ - - // Populate the class2type map - jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), - function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); - } ); - - function isArrayLike( obj ) { - - // Support: iOS 8.2 (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = jQuery.type( obj ); - - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; - } - var Sizzle = - /*! - * Sizzle CSS Selector Engine v2.2.1 - * http://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2015-10-17 - */ - (function( window ) { - - var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // http://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }; - - // Optimize for push.apply( _, NodeList ) - try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; - } catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; - } - - function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, nidselect, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - - // ID selector - if ( (m = match[1]) ) { - - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { - - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", (nid = expando) ); - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']"; - while ( i-- ) { - groups[i] = nidselect + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); - } - - /** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ - function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; - } - - /** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ - function markFunction( fn ) { - fn[ expando ] = true; - return fn; - } - - /** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ - function assert( fn ) { - var div = document.createElement("div"); - - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } - } - - /** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ - function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } - } - - /** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ - function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; - } - - /** - * Returns a function to use in pseudos for input types - * @param {String} type - */ - function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; - } - - /** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ - function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; - } - - /** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ - function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); - } - - /** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ - function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; - } - - // Expose support vars for convenience - support = Sizzle.support = {}; - - /** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ - isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; - }; - - /** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ - setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, parent, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9-11, Edge - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( (parent = document.defaultView) && parent.top !== parent ) { - // Support: IE 11 - if ( parent.addEventListener ) { - parent.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", unloadHandler ); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var m = context.getElementById( id ); - return m ? [ m ] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - docElem.appendChild( div ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibing-combinator selector` fails - if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); - - assert(function( div ) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( div.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return document; - }; - - Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); - }; - - Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - !compilerCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch (e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; - }; - - Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); - }; - - Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; - }; - - Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); - }; - - /** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ - Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; - }; - - /** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ - getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; - }; - - Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - // Use previously-cached element index if available - if ( useCache ) { - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } - }; - - Expr.pseudos["nth"] = Expr.pseudos["eq"]; - - // Add button/input type pseudos - for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); - } - for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); - } - - // Easy API for creating new setFilters - function setFilters() {} - setFilters.prototype = Expr.filters = Expr.pseudos; - Expr.setFilters = new setFilters(); - - tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); - }; - - function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; - } - - function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); - - if ( (oldCache = uniqueCache[ dir ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ dir ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - }; - } - - function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; - } - - function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; - } - - function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; - } - - function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); - } - - function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); - } - - function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context === document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - if ( !context && elem.ownerDocument !== document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; - } - - compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; - }; - - /** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ - select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; - }; - - // One-time assignments - - // Sort stability - support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - - // Support: Chrome 14-35+ - // Always assume duplicates if they aren't passed to the comparison function - support.detectDuplicates = !!hasDuplicate; - - // Initialize against the default document - setDocument(); - - // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) - // Detached nodes confoundingly follow *each other* - support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; - }); - - // Support: IE<8 - // Prevent attribute/property "interpolation" - // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx - if ( !assert(function( div ) { - div.innerHTML = ""; - return div.firstChild.getAttribute("href") === "#" ; - }) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); - } - - // Support: IE<9 - // Use defaultValue in place of getAttribute("value") - if ( !support.attributes || !assert(function( div ) { - div.innerHTML = ""; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; - }) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); - } - - // Support: IE<9 - // Use getAttributeNode to fetch booleans when getAttribute lies - if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; - }) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); - } - - return Sizzle; - - })( window ); - - - - jQuery.find = Sizzle; - jQuery.expr = Sizzle.selectors; - jQuery.expr[ ":" ] = jQuery.expr.pseudos; - jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; - jQuery.text = Sizzle.getText; - jQuery.isXMLDoc = Sizzle.isXML; - jQuery.contains = Sizzle.contains; - - - - var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; - }; - - - var siblings = function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; - }; - - - var rneedsContext = jQuery.expr.match.needsContext; - - var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ ); - - - - var risSimple = /^.[^:#\[\.,]*$/; - - // Implement the identical functionality for filter and not - function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - } ); - - } - - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - - } - - if ( typeof qualifier === "string" ) { - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } - - qualifier = jQuery.filter( qualifier, elements ); - } - - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } - - jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); - }; - - jQuery.fn.extend( { - find: function( selector ) { - var i, - len = this.length, - ret = [], - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } - } ); - - - // Initialize a jQuery object - - - // A central reference to the root jQuery(document) - var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); - - // Support: Blackberry 4.6 - // gEBID returns nodes no longer in the document (#6963) - if ( elem && elem.parentNode ) { - - // Inject the element directly into the jQuery object - this.length = 1; - this[ 0 ] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }; - - // Give the init function the jQuery prototype for later instantiation - init.prototype = jQuery.fn; - - // Initialize central reference - rootjQuery = jQuery( document ); - - - var rparentsprev = /^(?:parents|prev(?:Until|All))/, - - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - - jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( pos ? - pos.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } - } ); - - function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; - } - - jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - return elem.contentDocument || jQuery.merge( [], elem.childNodes ); - } - }, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; - } ); - var rnotwhite = ( /\S+/g ); - - - - // Convert String-formatted options into Object-formatted ones - function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; - } - - /* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ - jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( jQuery.isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; - }; - - - jQuery.extend( { - - Deferred: function( func ) { - var tuples = [ - - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], - [ "notify", "progress", jQuery.Callbacks( "memory" ) ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this === promise ? newDefer.promise() : this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( function() { - - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || - ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. - // If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // Add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .progress( updateFunc( i, progressContexts, progressValues ) ) - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ); - } else { - --remaining; - } - } - } - - // If we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } - } ); - - - // The deferred used on DOM ready - var readyList; - - jQuery.fn.ready = function( fn ) { - - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; - }; - - jQuery.extend( { - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.triggerHandler ) { - jQuery( document ).triggerHandler( "ready" ); - jQuery( document ).off( "ready" ); - } - } - } ); - - /** - * The ready event handler and self cleanup method - */ - function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); - } - - jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called - // after the browser event has already occurred. - // Support: IE9-10 only - // Older IE sometimes signals "interactive" too soon - if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); - - } else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); - } - } - return readyList.promise( obj ); - }; - - // Kick off the DOM ready check even if the user does not - jQuery.ready.promise(); - - - - - // Multifunctional method to get and set values of a collection - // The value/s can optionally be executed if it's a function - var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !jQuery.isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - len ? fn( elems[ 0 ], key ) : emptyGet; - }; - var acceptData = function( owner ) { - - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - /* jshint -W018 */ - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); - }; - - - - - function Data() { - this.expando = jQuery.expando + Data.uid++; - } - - Data.uid = 1; - - Data.prototype = { - - register: function( owner, initial ) { - var value = initial || {}; - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable, non-writable property - // configurability must be true to allow the property to be - // deleted with the delete operator - } else { - Object.defineProperty( owner, this.expando, { - value: value, - writable: true, - configurable: true - } ); - } - return owner[ this.expando ]; - }, - cache: function( owner ) { - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( !acceptData( owner ) ) { - return {}; - } - - // Check if the owner object already has a cache - var value = owner[ this.expando ]; - - // If not, create one - if ( !value ) { - value = {}; - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); - } - } - } - - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); - - // Handle: [ owner, key, value ] args - if ( typeof data === "string" ) { - cache[ data ] = value; - - // Handle: [ owner, { properties } ] args - } else { - - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ prop ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : - owner[ this.expando ] && owner[ this.expando ][ key ]; - }, - access: function( owner, key, value ) { - var stored; - - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { - - stored = this.get( owner, key ); - - return stored !== undefined ? - stored : this.get( owner, jQuery.camelCase( key ) ); - } - - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, name, camel, - cache = owner[ this.expando ]; - - if ( cache === undefined ) { - return; - } - - if ( key === undefined ) { - this.register( owner ); - - } else { - - // Support array or space separated string of keys - if ( jQuery.isArray( key ) ) { - - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = key.concat( key.map( jQuery.camelCase ) ); - } else { - camel = jQuery.camelCase( key ); - - // Try the string as a key before any manipulation - if ( key in cache ) { - name = [ key, camel ]; - } else { - - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - name = camel; - name = name in cache ? - [ name ] : ( name.match( rnotwhite ) || [] ); - } - } - - i = name.length; - - while ( i-- ) { - delete cache[ name[ i ] ]; - } - } - - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - - // Support: Chrome <= 35-45+ - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://code.google.com/p/chromium/issues/detail?id=378607 - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; - } else { - delete owner[ this.expando ]; - } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } - }; - var dataPriv = new Data(); - - var dataUser = new Data(); - - - - // Implementation Summary - // - // 1. Enforce API surface and semantic compatibility with 1.9.x branch - // 2. Improve the module's maintainability by reducing the storage - // paths to a single mechanism. - // 3. Use the same single mechanism to support "private" and "user" data. - // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) - // 5. Avoid exposing implementation details on user objects (eg. expando properties) - // 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - - var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; - - function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; - } - - jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } - } ); - - jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); - - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } - - return access( this, function( value ) { - var data, camelKey; - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - - // Attempt to get data from the cache - // with the key as-is - data = dataUser.get( elem, key ) || - - // Try to find dashed key if it exists (gh-2779) - // This is for 2.2.x only - dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() ); - - if ( data !== undefined ) { - return data; - } - - camelKey = jQuery.camelCase( key ); - - // Attempt to get data from the cache - // with the key camelized - data = dataUser.get( elem, camelKey ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, camelKey, undefined ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - camelKey = jQuery.camelCase( key ); - this.each( function() { - - // First, attempt to store a copy or reference of any - // data that might've been store with a camelCased key. - var data = dataUser.get( this, camelKey ); - - // For HTML5 data-* attribute interop, we have to - // store property names with dashes in a camelCase form. - // This might not apply to all properties...* - dataUser.set( this, camelKey, value ); - - // *... In the case of properties that might _actually_ - // have dashes, we need to also store a copy of that - // unchanged property. - if ( key.indexOf( "-" ) > -1 && data !== undefined ) { - dataUser.set( this, key, value ); - } - } ); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); - } - } ); - - - jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } - } ); - - jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } - } ); - var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - - var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - - - var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - - var isHidden = function( elem, el ) { - - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || - !jQuery.contains( elem.ownerDocument, elem ); - }; - - - - function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, - scale = 1, - maxIterations = 20, - currentValue = tween ? - function() { return tween.cur(); } : - function() { return jQuery.css( elem, prop, "" ); }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - do { - - // If previous iteration zeroed out, double until we get *something*. - // Use string for doubling so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - initialInUnit = initialInUnit / scale; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Update scale, tolerating zero or NaN from tween.cur() - // Break the loop if scale is unchanged or perfect, or if we've just had enough. - } while ( - scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations - ); - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; - } - var rcheckableType = ( /^(?:checkbox|radio)$/i ); - - var rtagName = ( /<([\w:-]+)/ ); - - var rscriptType = ( /^$|\/(?:java|ecma)script/i ); - - - - // We have to close these tags to support XHTML (#13200) - var wrapMap = { - - // Support: IE9 - option: [ 1, "" ], - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] - }; - - // Support: IE9 - wrapMap.optgroup = wrapMap.option; - - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; - wrapMap.th = wrapMap.td; - - - function getAll( context, tag ) { - - // Support: IE9-11+ - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( tag || "*" ) : - typeof context.querySelectorAll !== "undefined" ? - context.querySelectorAll( tag || "*" ) : - []; - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], ret ) : - ret; - } - - - // Mark scripts as having already been evaluated - function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } - } - - - var rhtml = /<|&#?\w+;/; - - function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - - // Support: Android<4.1, PhantomJS<2 - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: Android<4.1, PhantomJS<2 - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; - } - - - ( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0-4.3, Safari<=5.1 - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Safari<=5.1, Android<4.2 - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE<=11+ - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; - } )(); - - - var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - - function returnTrue() { - return true; - } - - function returnFalse() { - return false; - } - - // Support: IE9 - // See #13393 for more info - function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } - } - - function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); - } - - /* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ - jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = {}; - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); - - var i, j, ret, matched, handleObj, - handlerQueue = [], - args = slice.call( arguments ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, matches, sel, handleObj, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Support (at least): Chrome, IE9 - // Find delegate handlers - // Black-hole SVG instance trees (#13180) - // - // Support: Firefox<=42+ - // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) - if ( delegateCount && cur.nodeType && - ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push( { elem: cur, handlers: matches } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + - "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split( " " ), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " + - "screenX screenY toElement" ).split( " " ), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + - ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + - ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; - - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = new jQuery.Event( originalEvent ); - - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Support: Cordova 2.5 (WebKit) (#13255) - // All events should have a target; Cordova deviceready doesn't - if ( !event.target ) { - event.target = document; - } - - // Support: Safari 6.0+, Chrome<28 - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - } - }; - - jQuery.removeEvent = function( elem, type, handle ) { - - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } - }; - - jQuery.Event = function( src, props ) { - - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android<4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; - }; - - // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding - // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html - jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } - }; - - // Create mouseenter/leave events using mouseover/out and event-time checks - // so that event delegation works in jQuery. - // Do the same for pointerenter/pointerleave and pointerover/pointerout - // - // Support: Safari 7 only - // Safari sends mouseenter too often; see: - // https://code.google.com/p/chromium/issues/detail?id=470258 - // for the description of the bug (it existed in older Chrome versions as well). - jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" - }, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; - } ); - - jQuery.fn.extend( { - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } - } ); - - - var - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, - - // Support: IE 10-11, Edge 10240+ - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; - - // Manipulating tables requires a tbody - function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? - - elem.getElementsByTagName( "tbody" )[ 0 ] || - elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) : - elem; - } - - // Replace/restore the type attribute of script elements for safe DOM manipulation - function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; - } - function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - - if ( match ) { - elem.type = match[ 1 ]; - } else { - elem.removeAttribute( "type" ); - } - - return elem; - } - - function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - dataUser.set( dest, udataCur ); - } - } - - // Fix IE bugs, see support tests - function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } - } - - function domManip( collection, args, callback, ignored ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android<4.1, PhantomJS<2 - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); - } - } - } - } - } - } - - return collection; - } - - function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; - - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } - - if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } - - return elem; - } - - jQuery.extend( { - htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; - - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Support: Chrome <= 35-45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { - - // Support: Chrome <= 35-45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } - } ); - - jQuery.fn.extend( { - - // Keep domManip exposed until 3.0 (gh-2225) - domManip: domManip, - - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } - } ); - - jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" - }, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: QtWebKit - // .get() because push.apply(_, arraylike) throws - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; - } ); - - - var iframe, - elemdisplay = { - - // Support: Firefox - // We have to pre-define these values for FF (#10227) - HTML: "block", - BODY: "block" - }; - - /** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ - - // Called only from within defaultDisplay - function actualDisplay( name, doc ) { - var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - - display = jQuery.css( elem[ 0 ], "display" ); - - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); - - return display; - } - - /** - * Try to determine the default display value of an element - * @param {String} nodeName - */ - function defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; - - if ( !display ) { - display = actualDisplay( nodeName, doc ); - - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { - - // Use the already-created iframe if possible - iframe = ( iframe || jQuery( "