{"version":3,"sources":["src/animation.js","cytoscape.min.js","src/collection/algorithms/a-star.js","src/collection/algorithms/bellman-ford.js","src/collection/algorithms/betweenness-centrality.js","src/collection/algorithms/bfs-dfs.js","src/collection/algorithms/closeness-centrality.js","src/collection/algorithms/degree-centrality.js","src/collection/algorithms/floyd-warshall.js","src/collection/algorithms/index.js","src/collection/algorithms/kerger-stein.js","src/collection/algorithms/page-rank.js","src/collection/animation.js","src/collection/class.js","src/collection/comparators.js","src/collection/compounds.js","src/collection/data.js","src/collection/degree.js","src/collection/dimensions.js","src/collection/element.js","src/collection/events.js","src/collection/filter.js","src/collection/group.js","src/collection/index.js","src/collection/iteration.js","src/collection/layout.js","src/collection/style.js","src/collection/switch-functions.js","src/collection/traversing.js","src/collection/zsort.js","src/core/add-remove.js","src/core/animation.js","src/core/events.js","src/core/export.js","src/core/index.js","src/core/layout.js","src/core/notification.js","src/core/renderer.js","src/core/search.js","src/core/style.js","src/core/viewport.js","src/define.js","src/event.js","src/extension.js","src/extensions/index.js","src/extensions/layout/breadthfirst.js","src/extensions/layout/circle.js","src/extensions/layout/concentric.js","src/extensions/layout/cose.js","src/extensions/layout/grid.js","src/extensions/layout/index.js","src/extensions/layout/null.js","src/extensions/layout/preset.js","src/extensions/layout/random.js","src/extensions/renderer/base/arrow-shapes.js","src/extensions/renderer/base/cached-eles.js","src/extensions/renderer/base/coord-ele-math.js","src/extensions/renderer/base/images.js","src/extensions/renderer/base/index.js","src/extensions/renderer/base/load-listeners.js","src/extensions/renderer/base/node-shapes.js","src/extensions/renderer/base/redraw.js","src/extensions/renderer/canvas/arrow-shapes.js","src/extensions/renderer/canvas/drawing-edges.js","src/extensions/renderer/canvas/drawing-images.js","src/extensions/renderer/canvas/drawing-label-text.js","src/extensions/renderer/canvas/drawing-nodes.js","src/extensions/renderer/canvas/drawing-redraw.js","src/extensions/renderer/canvas/drawing-shapes.js","src/extensions/renderer/canvas/export-image.js","src/extensions/renderer/canvas/index.js","src/extensions/renderer/canvas/node-shapes.js","src/extensions/renderer/index.js","src/extensions/renderer/null/index.js","src/fabric.js","src/heap.js","src/index.js","src/is.js","src/jquery-plugin.js","src/math.js","src/promise.js","src/selector.js","src/style/apply.js","src/style/bypass.js","src/style/container.js","src/style/get-for-ele.js","src/style/index.js","src/style/json.js","src/style/parse.js","src/style/properties.js","src/style/string-sheet.js","src/stylesheet.js","src/thread.js","src/util/colors.js","src/util/index.js","src/util/maps.js","src/util/memoize.js","src/util/regex.js","src/util/strings.js","src/util/timing.js","src/window.js"],"names":["f","exports","module","define","amd","g","window","global","self","this","cytoscape","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length",1,"_dereq_","util","is","Promise","Animation","target","opts","opts2","_p","_private","extend","duration","style","css","started","playing","hooked","applying","progress","completes","frames","complete","fn","push","anifn","prototype","instanceString","hook","q","tAni","animation","queue","current","elementOrCollection","cy","addToAnimationPool","play","stopped","apply","pause","stop","rewind","fastforward","time","undefined","p","wasPlaying","completed","reverse","swap","b","_pa","prop","name","startStyleProp","startStyle","dash2camel","promise","type","arr","resolve","reject","./is","./promise","./util",2,"elesfn","aStar","options","eles","reconstructPath","start","end","cameFromMap","pathAcum","getElementById","previous","previousEdge","cameFromEdge","findMin","openSet","fScore","minPos","tempScore","root","source","string","filter","goal","heuristic","weight","weightFn","directed","closedSet","id","cameFrom","gScore","edges","stdFilter","isLoop","nodes","steps","cMin","rPath","found","distance","path","spawn","splice","vwEdges","connectedEdges","ele","data","intersect","w","connectedNodes","indexOf","../../is",3,"bellmanFord","numNodes","id2position","cost","predecessor","predEdge","Infinity","flag","sourceIndex","targetIndex","temp","error","pathTo","distanceTo","hasNegativeWeightCycle","position2id","res","to","toId","reconstructPathAux","fromPos","toPos","acumPath","predPos","../../util",4,"betweennessCentrality","weighted","bool","priorityInsert","unshift","d","tmp","V","A","C","outgoers","openNeighborhood","S","P","Q","Number","POSITIVE_INFINITY","v","pop","forEach","$","edgesTo","edge","edgeWeight","max","key","ret","betweenness","node","betweennessNormalized","betweennessNormalised","bc",5,"Heap","defineSearch","params","bfs","dfs","roots","std","thisArg","plainObject","visit","arguments","connectedBy","id2depth","j","isNode","shift","depth","prevEdge","prevNode","not","connectedEles","collection","unique","breadthFirstSearch","depthFirstSearch","kruskal","findSet","forest","anySame","index","toArray","sort","weightA","weightB","setU","setV","add","dijkstra","dist","prev","knownDist","getDist","setDist","updateItem","same","distBetween","smallestEdge","uvs","edgesWith","smallestDistance","size","smalletsDist","uid","Math","Infinite","neighbors","neighborhood","vid","vDist","alt","../../heap",6,"closenessCentralityNormalized","harmonic","closenesses","maxCloseness","fw","floydWarshall","currCloseness","closeness","closenessCentrality","totalDistance","cc","ccn","closenessCentralityNormalised",7,"degreeCentralityNormalized","indegrees","outdegrees","maxIndegree","maxOutdegree","currDegree","degreeCentrality","indegree","outdegree","degrees","maxDegree","degree","callingEles","alpha","number","incoming","intersection","outgoing","k_in","k_out","s_in","s_out","pow","connEdges","k","dc","dcn","degreeCentralityNormalised",8,"newRow","Array","next","edgeNext","initMatrix","from","fromId","pathArr",9,"props","./a-star","./bellman-ford","./betweenness-centrality","./bfs-dfs","./closeness-centrality","./degree-centrality","./floyd-warshall","./kerger-stein","./page-rank",10,"kargerStein","colapse","edgeIndex","nodeMap","remainingEdges","edgeInfo","sourceIn","targetIn","partition1","partition2","newEdges","slice","contractUntil","metaNodeMap","sizeLimit","floor","random","numEdges","numIter","ceil","log","LN2","stopSize","sqrt","edgeIndexes","minCut","minCutSize","originalMetaNode","iter","edgesState","metaNodeMap2","res1","res2","resEdges","map","witnessNodePartition","partitionId","cut",11,"pageRank","normalizeVector","vector","total","dampingFactor","precision","epsilon","iterations","matrix","columnSum","additionalProb","eigenvector","nullVector","diff","rank","nodeId",12,"animate","animated","clearQueue","delay","delayAnimation","../define",13,"classes","match","changed","classesMap","cls","eleClasses","changedEle","eleHasClass","eleCls","specdClass","copy","updateStyle","trigger","addClass","toggleClass","hasClass","className","classesStr","toggle","il","shouldAdd","removeClass","flashClass","setTimeout","../util",14,"allAre","selector","some","every","allAreNeighbors","allAreNeighbours",15,"parent","parents","nonempty","commonAncestors","ancestors","orphans","empty","nonorphans","children","concat","siblings","isParent","isChild","descendants","elements",16,"field","bindingEvent","allowBinding","allowSetting","settingEvent","settingTriggersEvent","triggerFnName","allowGetting","immutableKeys","removeData","event","triggerEvent","scratch","removeScratch","rscratch","removeRscratch","attr","removeAttr",17,"defineDegreeFunction","callback","includeLoops","removed","defineDegreeBoundsFunction","degreeFn","minDegree","min","minIndegree","minOutdegree","totalDegree",18,"position","validKeys","onSet","updatedEles","updateCompoundBounds","rtrigger","canSet","locked","silentPosition","positions","pos","silent","elePos","x","y","toTrigger","silentPositions","renderedPosition","dim","val","zoom","pan","rpos","setting","relativePosition","ppos","hasCompoundNodes","hasParent","relativeToParent","origin","renderedBoundingBox","bb","boundingBox","x1","x2","y1","y2","h","update","includeLabels","value","includeEdges","padding","top","pfValue","bottom","left","right","didUpdate","autoWidth","autoHeight","updated","styleEnabled","cy_p","staticEmptyObject","includeNodes","renderer","recalculateRenderedStyle","ex1","ex2","ey1","ey2","display","group","includedEle","outerWidth","halfW","outerHeight","halfH","isEdge","n1","n1_p","n1pos","n2","n2_p","n2pos","rstyle","wHalf","pts","bezierPts","linePts","pt","strValue","hpts","haystackPts","label","fontSize","halign","valign","labelWidth","labelHeight","labelX","labelY","autorotate","lx1","lx2","ly1","ly2","lh","lw","theta","labelAngle","cos","sin","rotate","px1y1","px1y2","px2y1","px2y2","noninf","defineDimFns","uppercaseName","capitalize","autoName","labelName","outerName","uppercaseOuterName","border","paddings","od","modelPosition","point","modelPositions","points","renderedPoint","relativePoint","boundingbox","renderedBoundingbox","../is",19,"Element","restore","core","single","listeners","styleCxts","selected","selectable","grabbed","grabbable","active","split","applyBypass",20,"on","one","unbindSelfOnTrigger","once","unbindAllBindersOnTrigger","off","extraParams","notify","eventAliasesOn",21,"Selector","element","toRemove","remove","ids","absoluteComplement","other","col1","col2","col1Smaller","ids2","col","xor","inOther","both","retEles","toAdd","merge","toAddEle","indexes","unmergeOne","unmergedLastEle","lastEleI","lastEle","unmerge","mapFn","filterEles","include","valFn","maxEle","minEle","union","or","difference","relativeComplement","subtract","and","symmetricDifference","symdiff","fnFilter","filterFn","complement","abscomp","../selector",22,"isSimple",23,"idFactory","prefix","generate","tryThisId","Collection","createdElements","elesIds","json","obj","startBatch","checkSwitch","trueFnName","falseFnName","obj_k","endBatch","join","jsons","clone","elesArr","notifyRenderer","restored","emptyString","fields","fieldsLength","badSourceOrTarget","src","tgt","addToPool","parentId","specifiedParent","selfAsParent","ancestor","toUpdateStyle","inside","addConnectedEdges","addChildren","alreadyAdded","elesToRemoveIds","elesToRemove","removeEdgeRef","connectedEdge","removeChildRef","removeFromPool","elesStillInside","removedElements","checkedParentId","move","struct","srcId","tgtId","srcExists","tgtExists","parentExists","descs","descsEtc","./algorithms","./animation","./class","./comparators","./compounds","./data","./degree","./dimensions","./element","./events","./filter","./group","./index","./iteration","./layout","./style","./switch-functions","./traversing",24,"zIndexSort","each","array","thisSize","eq","first","last","sortFn","sorted","sortByZIndex","zDepth","MAX_VALUE","srcDepth","tgtDepth","./zsort",25,"layoutPositions","layout","animations","lastNode","newPos","ani","animationDuration","easing","animationEasing","step","fit","ready","makeLayout","createLayout",26,"batchingStyle","bEles","batchStyleEles","updatedCompounds","toNotify","updateMappers","renderedCss","property","renstyle","getRenderedStyle","updateTransitions","getStylePropertyValue","getRawStyle","removeCss","names","removeAllBypasses","removeBypasses","show","hide","visible","pStyle","pVis","pDis","hidden","effectiveOpacity","parentOpacity","opacity","transparent","isFullAutoParent","autoW","autoH","backgrounding","bypass","renderedStyle","removeBypass","removeStyle",27,"defineSwitchFunction","args","changedEles","handler","bind","able","ableField","overrideAble","changedColl","defineSwitchSet","overrideField","autolock","autoungrabify","autounselectify","deselect","unselect","inactive",28,"defineSourceFunction","sources","defineEdgesWithFunction","otherNodes","thisIds","otherIds","edgeData","thisToOther","otherToThis","edgeConnectsThisAndOther","thisIs","defineParallelEdgesFunction","defaults","codirected","edge1","src1","srcid1","tgt1","tgtid1","srcEdges1","edge2","edge2data","tgtid2","srcid2","oppdirected","hasEdgesPointingIn","leaves","hasEdgesPointingOut","oEles","eleId","successors","sEles","sElesIds","newOutgoers","outgoer","outgoerId","incomers","predecessors","pEles","pElesIds","newIncomers","incomer","incomerId","otherNode","closedNeighborhood","neighbourhood","closedNeighbourhood","openNeighbourhood","targets","parallelEdges","codirectedEdges","components","visited","unvisited","visitInComponent","component",29,"a_p","b_p","zDiff","depthA","depthB","aIsNode","aIsEdge","bIsNode","bIsEdge","depthDiff","sameDepth",30,"corefn","document","elesByGroup","grs","elesArray","jl","load","onload","ondone","notifications","oldEles","layoutOpts","../collection","../collection/element","../extensions/renderer/null","../window",31,"aniEles","stopAnimationLoop","animationsRunning","startAnimationLoop","globalAnimationStep","requestAnimationFrame","now","handleElements","handleElement","isCore","ranAnis","callbacks","cb","ani_p","startAnimation","doneEles","ranEleAni","handledThisEle","ranCoreAni","isEles","startPosition","getValueStyle","startPan","startZoom","startTime","pEasing","easingImpl","easings","easingVals","easingProp","parse","percent","startPos","endPos","valid","ease","endPan","animatingPan","endZoom","animatingZoom","easedVal","overrideBypass","evalCubicBezier","p1","p2","one_t","tsq","cubicBezier","startProp","endProp","easingFn","easedArr","si","ei","roundValue","round","generateSpringRK4","springAccelerationForState","state","tension","friction","springEvaluateStateWithDerivative","initialState","dt","derivative","dx","dv","springIntegrateState","c","dxdt","dvdt","springRK4Factory","have_duration","last_state","initState","time_lapsed","tolerance","DT","parseFloat","abs","percentComplete","linear","ease-in","ease-out","ease-in-out","ease-in-sine","ease-out-sine","ease-in-out-sine","ease-in-quad","ease-out-quad","ease-in-out-quad","ease-in-cubic","ease-out-cubic","ease-in-out-cubic","ease-in-quart","ease-out-quart","ease-in-out-quart","ease-in-quint","ease-out-quint","ease-in-out-quint","ease-in-expo","ease-out-expo","ease-in-out-expo","ease-in-circ","ease-out-circ","ease-in-out-circ","spring","cubic-bezier",32,33,"png","jpg","bg","jpeg",34,"Core","container","htmlElement","reg","_cyreg","destroy","readies","head","headless","defVal","def","altVal","initrender","id2index","onRenders","notificationsEnabled","minZoom","maxZoom","zoomingEnabled","userZoomingEnabled","panningEnabled","userPanningEnabled","boxSelectionEnabled","autolockNodes","autoungrabifyNodes","deferredExecQueue","selType","selectionType","loadExtData","anyIsPromise","extData","datum","all","then","initRenderer","hideEdgesOnViewport","hideLabelsOnViewport","textureOnViewport","wheelSensitivity","motionBlur","motionBlurOpacity","pixelRatio","desktopTapThreshold","touchTapThreshold","thens","initStyle","initEles","setStyle","done","isReady","domEle","childNodes","removeChild","alreadyInPool","inPool","jid","idInJson","updateEles","gr","../promise","./add-remove","./export","./notification","./renderer","./search","./viewport",35,"prevLayout","run","Layout","extension",36,"batchingNotify","batchNotifyEles","bTypes","batchNotifyTypes","noNotifications","batchCount","batch","batchData",37,"renderTo","context","pxRatio","forceRender","resize","RendererProto","rOpts","init","triggerOnRender","cbs","onRender","offRender","invalidateDimensions",38,39,"Style","newStyle","stylesheet","generateStyle","fromJson","fromString","../style",40,"dims","panBy","viewportState","getFitViewport","sel","bbe","width","height","isNaN","level","z","pan1","zoom1","zoom2","pan2","posChanged","viewport","zoomDefd","panDefd","events","zoomFailed","panFailed","cancelOnFailedZoom","center","getCenterPan","reset","clientWidth","clientHeight","extent","rb","renderedExtent","centre",41,"Event","selfIsArrayLike","keys","i_a","l_a","_privateFields","validKeyToDelete","regex","optionalTypeRegex","falseCallback","eventsIsString","evts","evt","namespace","listener","delegated","selObj","binders","proto","addListener","listen","removeListener","unlisten","unbind","emit","pon","promiseOn","offArgs","onArgs","nsMatches","typeMatches","cbMatches","listenerMatches","fnToTrigger","eventsIsObject","eventsIsEvent","hasCompounds","eventArgObj","evtObj","triggerer","triggererIsElement","bubbleUp","cyTarget","cyPosition","cyRenderedPosition","lis","targetMatches","matches","binder","binderListeners","m","binderListener","isPropagationStopped","stopPropagation","preventDefault","fnParams","properties","propertiesEmpty","getPropsList","cyPan","centerPan","fitVp","jumpToEnd","anis","./event","./selector",42,"returnFalse","returnTrue","originalEvent","isDefaultPrevented","message","timeStamp","Date","stopImmediatePropagation","isImmediatePropagationStopped",43,"setExtension","registrant","ext","layoutProto","Object","create","optLayoutFns","fnName","bProto","getExtension","rProto","pName","pVal","existsInR","clientFunctions","setMap","extensions","getMap","setModule","moduleType","moduleName","modules","getModule","incExts","impl","./collection","./core","./define","./extensions",44,45,"BreadthFirstLayout","math","circle","spacingFactor","avoidOverlap","maximalAdjustments","graph","makeBoundingBox","rootsArray","unhandledNodes","currComp","pNode","comp","compRoots","depths","foundByBfs","prevId","succ","orphanNodes","maxChecks","checks","assignedDepth","assignDepthsToEles","breadthfirst","intersectsDepth","highestOther","thisInfo","highestDepthOfOther","otherInfo","adj","nDepths","elesToMove","nDepth","info","intEle","intInfo","newDepth","minDistance","nbb","cachedWeightedPercent","getWeightedPercent","eleDepth","samples","neighbor","bf","apct","bpct","times","biggestDepthSize","getPosition","isBottomDepth","depthSize","distanceX","distanceY","radiusStepSize","radius","PI","epos","../../math",46,"CircleLayout","startAngle","sweep","clockwise","counterclockwise","dTheta","dcos","dsin","rMin","getPos","rx","ry",47,"ConcentricLayout","equidistant","minNodeSpacing","concentric","levelWidth","nodeValues","maxNodeSize","levels","currentLevel","minDist","firstLvlHasMulti","maxR","rStep","rDeltaMax","rDelta",48,"CoseLayout","DEBUG","Thread","animationThreshold","refresh","componentSpacing","nodeRepulsion","nodeOverlap","idealEdgeLength","edgeElasticity","nestingFactor","gravity","initialTemp","coolingFactor","minTemp","useMultitasking","thread","disabled","debug","layoutInfo","createLayoutInfo","printLayoutInfo","randomizePositions","refreshRequested","force","refreshPositions","layoutNodes","pass","loopRet","calculateNodeForces","calculateEdgeForces","calculateGravityForces","propagateForces","updatePositions","graphSet","node1","idToIndex","node2","cmptId1","cmptId","cmptId2","isCompound","directionX","positionX","directionY","positionY","overlap","nodesOverlap","forceX","forceY","point1","findClippingPoint","point2","distanceSqr","isLocked","offsetX","offsetY","dX","dY","overlapX","maxX","minX","overlapY","maxY","minY","X","Y","H","W","dirSlope","nodeSlope","edgeSize","layoutEdges","sourceIx","sourceId","targetIx","targetId","lx","ly","idealLength","elasticity","distThreshold","centerX","centerY","dy","fx","fy","nodeIndex","offX","offY","childNode","nodeSize","tempForce","limitForce","temperature","updateAncestryBoundaries","padRight","padLeft","padBottom","padTop","separateComponents","layutInfo","cid","totalA","c1","c2","usedW","rowH","maxRowW","mainLoop","broadcast","layoutInfoUpdated","indexToGraph","id2cmptId","tempNode","tempGraph","p_id","node_id","node_ix","tempEdge","sourceGraph","targetGraph","lca","findLCA","lcaGraph","findLCA_aux","count","graphIx","nodeIx","childGraphIx","result","console","toString","set","coseBB","lnode","pctX","pctY","../../thread",49,"GridLayout","avoidOverlapPadding","condense","rows","cols","cells","splits","small","large","oRows","oCols","columns","sm","lg","cellWidth","cellHeight","cellUsed","used","row","use","moveToNextCell","id2manPos","rcPos",50,"./breadthfirst","./circle","./concentric","./cose","./grid","./null","./preset","./random",51,"NullLayout",52,"PresetLayout","posIsFn",53,"RandomLayout",54,"BRp","arrowShapeHeight","registerArrowShapes","arrowShapes","bbCollide","angle","translation","transform","xRotated","yRotated","xScaled","yScaled","xTranslated","yTranslated","transformPoints","retPts","pointsToArr","defineArrowShape","defn","collide","pointInsidePolygonPoints","roughCollide","draw","arrowShapeImpl","spacing","gap","falsify","noop","zeroify","controlPoint","ptsTrans","ctrlPt","ctrlPtTrans","pointsTee","triPts","teePts","leavePathOpen","matchEdgeWidth","getArrowWidth","../../../is","../../../math","../../../util",55,"delEleCache","eleEache","getEleCache","getCachedElements","getCachedNodes","getCachedEdges","updateElementsCache",56,"pushBezierPts","qbezierAt","p3","bpts","projectIntoViewport","clientX","clientY","offsets","findContainerClientCoords","offsetLeft","offsetTop","containerBB","getBoundingClientRect","invalidateContainerClientCoordsCache","findNearestElement","visibleElementsOnly","isTouch","checkNode","nodeThreshold","hw","hh","shape","nodeShapes","getNodeShape","checkPoint","near","checkEdge","sqDist","passedVisibilityCheck","rs","edgeThreshold","widthSq","width2","inEdgeBB","passesVisibilityCheck","edgeType","allpts","inLineVicinity","sqDistanceToFiniteLine","inBezierVicinity","sqDistanceToQuadraticBezier","eWidth","arSize","arrows","arrowStartX","arrowStartY","srcArrowAngle","arrowEndX","arrowEndY","tgtArrowAngle","midX","midY","midsrcArrowAngle","midtgtArrowAngle","ar","checkLabel","th","labelThreshold","inBoundingBox","getCachedZSortedEles","getAllInBox","box","x1c","x2c","y1c","y2c","boxBb","nodeBb","boundingBoxesIntersect","startX","startY","endX","endY","allInside","pointInBoundingBox","makePolygon","updateCachedZSortedEles","forceRecalc","lastNodes","lastZOrderCachedNodes","lastEdges","lastZOrderCachedEdges","cachedZSortedEles","projectLines","et","lpts","projectBezier","recalculateNodeLabelProjection","content","textX","textY","nodeWidth","nodeHeight","nodePos","textHalign","textValign","applyLabelDimensions","recalculateEdgeLabelProjection","text","getLabelText","labelDims","calculateLabelDimensions","textTransform","toUpperCase","toLowerCase","labelWrapKey","labelKey","labelWrapCachedText","lines","maxW","wrappedLines","line","lineDims","lineW","words","subline","word","testLine","testDims","testW","labelWrapCachedLines","extraKey","fStyle","family","cacheKey","cache","labelDimCache","div","labelCalcDiv","createElement","body","appendChild","ds","fontFamily","fontStyle","fontWeight","zIndex","visibility","pointerEvents","lineHeight","whiteSpace","textContent","handledEdge","bbStyleSame","boundingBoxKey","labelStyleSame","styleSame","posSame","nodeX","nodeY","wSame","nodeW","hSame","nodeH","srcPos","tgtPos","srcSame","srcX","srcY","tgtSame","tgtX","tgtY","positionsSame","pEdge","pId","recalculateEdgeProjections","recalculateLabelProjections","findEdgeControlPoints","pairId","hashTable","pairIds","haystackEdges","autorotateEdges","curveStyle","edgeIsUnbundled","hasUnbundled","src_p","tgt_p","srcW","srcH","tgtW","tgtH","srcShape","tgtShape","vectorNormInverse","badBezier","pairEdges","srcOutside","intersectLine","tgtOutside","midptSrcPts","vectorNorm","edge_p","edgeIndex1","lastEdgeIndex","edgeIndex2","numEdges1","lastNumEdges","numEdges2","eStyle","ctrlptDists","ctrlptWs","bezierN","stepSize","ctrlptDist","ctrlptWeight","swappedDirection","srcX1","lastSrcCtlPtX","srcX2","srcY1","lastSrcCtlPtY","srcY2","srcW1","lastSrcCtlPtW","srcW2","srcH1","lastSrcCtlPtH","srcH2","tgtX1","lastTgtCtlPtX","tgtX2","tgtY1","lastTgtCtlPtY","tgtY2","tgtW1","lastTgtCtlPtW","tgtW2","tgtH1","lastTgtCtlPtH","tgtH2","width1","lastW","lastWidth","loopDist","ctrlpts","loopW","loopaPos","loopbPos","loopPos","minCompoundStretch","compoundStretchA","compoundStretchB","segpts","segmentWs","segmentDs","segmentsN","w1","w2","adjustedMidpt","multi","manctrlptDist","normctrlptDist","sign","signum","distanceFromMidpoint","findEndpoints","badStart","badAStart","badEnd","badAEnd","minCpADistFactor","arrowW","minCpADist","startACpDist","closeStartACp","endACpDist","closeEndACp","overlapping","cpD","cpL","cpM","cpProj","srcCtrlPtIntn","tgtCtrlPtIntn","mt","i2","i1","calculateArrowAngles","haystack","halfRadius","atan","midDispY","midDispX","getAngleFromDisp","dispX","dispY","atan2","isHaystack","isMultibezier","isSegments","isSelf","i3","bp0x","bp0y","bp1x","bp1y","cpts","p0","ic","tgtArShape","srcArShape","bezier","segments","cpStart","cpEnd","srcArrowFromPt","tgtArrowFromPt","arrowEnd","shortenIntersection","edgeEnd","arrowStart","edgeStart","badLine","getArrowHeight","edgeWidth","arrowWidthCache","cachedVal","../../../collection/zsort",57,"getCachedImage","url","onLoad","imageCache","image","Image","addEventListener",58,"BaseRenderer","BR","selection","hoverData","down","downTime","triggerMode","dragging","initialPan","capture","dragData","possibleDragElements","touchData","singleTouchStartTime","singleTouchMoved","earlier","redraws","showFps","motionBlurEnabled","forcedPixelRatio","motionBlurTransparency","motionBlurPxRatio","mbPxRBlurry","minMbLowQualFrames","fullQualityMb","clearedForMotionBlur","desktopTapThreshold2","touchTapThreshold2","tapholdDuration","bindings","registerNodeShapes","types","redrawHint","matchCanvasSize","startRenderLoop","redraw","destroyed","binding","removeEventListener","useCapture","removeObserver","disconnect","./arrow-shapes","./cached-eles","./coord-ele-math","./images","./load-listeners","./node-shapes","./redraw",59,"registerBinding","nodeIsDraggable","triggerEvents","isMultSelKeyDown","shiftKey","metaKey","ctrlKey","getDragListIds","listHasId","addToList","hasId","addDescendantsToDrag","inDragLayer","innerNodes","iNode","addNodeToDrag","updateAncestorsInDragLayer","freeDraggedElements","draggedElements","dEi_p","sEdges","MutationObserver","mutns","mutn","rNodes","removedNodes","rNode","parentNode","observe","childList","debounce","invalCtnrBBOnScroll","bbCtnr","inBoxSelection","which","select","mdownPos","checkForTaphold","tapholdCancelled","clearTimeout","tapholdTimeout","cxtStarted","cxtEvt","activate","getTime","cxtDragged","grabEvent","selectedNodes","bgActivePosistion","containerPageCoords","canvasWidth","canvasHeight","cyContainer","tParent","containerIsTarget","draggingEles","disp","dx2","dy2","dist2","rdist2","multSelKeyDown","updateDragDelta","dragDelta","cxtOver","deltaP","justStartedPan","mdPos","dragged","unactivate","justStartedDrag","didDrag","dEle","dPos","updatePos","tcol","selecting","cxtTap","newlySelected","newlySelCol","wheelHandler","scrollingPage","wheelZooming","wheelTimeout","deltaY","wheelDeltaY","wheelDelta","needsWheelFix","deltaMode","scrollingPageTimeout","f1x1","f1y1","f2x1","f2y1","distance1","distance1Sq","center1","modelCenter1","containerWidth","containerHeight","twoFingersStartInside","touchstartHandler","distanceSq","touches","release","cxtDistThreshold","cxtDistThresholdSq","near1","near2","cxt","draggedEles","touchDragEles","selectedNode","pinching","touchmoveHandler","f1x2","f1y2","f2x2","f2y2","distance2Sq","factorSq","distThresholdSq","factorThreshold","factorThresholdSq","lastThreeTouch","distance2","factor","df1x","df1y","df2x","df2y","tx","ty","ctrx","ctry","start_p","draggedEle","swipePanning","touchcancelHandler","touchendHandler","ctxTapend","ctxTap","updateStartStyle","startWasGrabbed","TouchEvent","pointers","makeTouch","identifier","pointerId","pageX","pageY","radiusX","radiusY","screenX","screenY","makePointer","touch","addPointer","removePointer","updatePointer","addTouchesToEvent","pointerType","../../../collection","../../../event",60,"generatePolygon","nodeShapeImpl","polygonIntersectLine","pointInsidePolygon","intersectLineEllipse","generateUnitNgonPointsFitToSquare","roundRectangleIntersectLine","cornerRadius","getRoundRectangleRadius","checkInEllipse","star5Points","outerPoints","generateUnitNgonPoints","innerPoints","innerRadius","fitPolygonToSquare",61,"timeToRender","redrawTotalTime","redrawCount","minRedrawLimit","maxRedrawLimit","forcedContext","averageRedrawTime","lastRedrawTime","redrawLimit","lastDrawTime","nowTime","timeElapsed","callAfterLimit","currentlyDrawing","requestedFrame","renderOptions","skipFrame","renderFn","performanceNow","render","endTime",62,"CRp","polygon","lineTo","triangle-backcurve","firstPt","quadraticCurveTo","triangle-tee","trianglePoints","teePoints","firstTeePt","moveTo","arc",63,"drawEdge","drawOverlayInstead","usePaths","overlayPadding","overlayOpacity","overlayColor","strokeStyle","lineCap","lineColor","lineStyle","lineWidth","shadowBlur","shadowOpacity","shadowColor","shadowOffsetX","shadowOffsetY","shadowStyle","drawEdgePath","drawArrowheads","canvasCxt","pathCacheHit","pathCacheKey","keyMatches","pathCache","Path2D","setLineDash","beginPath","stroke","drawArrowhead","arrowShape","gco","globalCompositeOperation","arrowClearFill","arrowFill","fillStyle","drawArrowShape","color","arrowType","fill","canvasContext","shapeImpl","arrowPathCacheKey","arrowPathCache","alreadyCached","closePath","lineJoin",64,"safeDrawImage","img","ix","iy","iw","ih","drawImage","canvasNeedsRedraw","NODE","DRAG","drawingImage","drawInscribedImage","xPos","yPos","repeat","clip","shouldClip","imgOpacity","imgW","cachedW","imgH","cachedH","offsetWidth","offsetHeight","bgW","units","bgH","scale","gAlpha","globalAlpha","save","pattern","createPattern","translate",65,"roundRect","ctx","drawEdgeText","wheel","computedSize","minSize","textAlign","textBaseline","drawText","drawNodeText","getFontCache","fontCaches","setupTextStyle","labelStyle","labelSize","labelFamily","labelWeight","outlineOpacity","outlineColor","fontCacheKey","fontKey","font","pLeft","pRight","pTop","pBottom","backgroundOpacity","borderOpacity","textBorderWidth","margin","bgWidth","bgHeight","bgX","bgY","textFill","textBackgroundColor","styleShape","fillRect","textStroke","textLineWidth","textBorderColor","textBorderStyle","strokeRect","whiteWidth","strokeText","fillText",66,"drawNode","prevBging","bgColor","borderColor","borderStyle","npos","darkness","borderWidth","hasPie","drawPie","nodeOpacity","cyStyle","pieSize","lastPercent","pieBackgroundN","angleStart","angleDelta","angleEnd",67,"motionBlurDelay","getPixelRatio","contexts","backingStore","backingStorePixelRatio","webkitBackingStorePixelRatio","mozBackingStorePixelRatio","msBackingStorePixelRatio","oBackingStorePixelRatio","devicePixelRatio","paintCache","caches","paintCaches","needToCreateCache","blur","mbPxRatio","bufferCanvases","MOTIONBLUR_BUFFER_NODE","MOTIONBLUR_BUFFER_DRAG","canvas","canvasContainer","CANVAS_LAYERS","canvases","BUFFER_COUNT","textureMult","TEXTURE_BUFFER","forcedZoom","forcedPan","drawAllLayers","forcedPxRatio","mbclear","setContextTransform","clear","ePan","eZoom","clearingMotionBlur","bufferContexts","effectivePan","effectiveZoom","setTransform","clearRect","drawElements","list","hideLabels","hideEdges","drawOnlyNodeLayer","needDraw","textureDraw","inNodeDragGesture","motionBlurFadeEffect","motionBlurTimeout","mbFrames","textureDrawLastFrame","SELECT_BOX","coreStyle","vp","prevVp","prevViewport","viewportIsDiff","drag","nondrag","textureCache","texture","mpan","outsideBgColor","outsideBgOpacity","vpManip","zEles","insideExtent","needMbClear","useBuffer","fps","maxFps","cxtNode","txtNode","cxtDrag","txtDrag","drawMotionBlur","txt","needClear","pxr","motionBlurCleared",68,"drawPolygonPath","drawRoundRectanglePath","halfWidth","halfHeight","arcTo","sin0","cos0","ellipseStepSize","drawEllipsePath","ellipse","rw","rh",69,"createBuffer","buffer","getContext","bufferCanvasImage","full","maxWidth","maxHeight","maxScaleW","maxScaleH","buffCanvas","buffCxt","rect","toDataURL",70,"CanvasRenderer","containerStyle","setAttribute","overflow","getAttribute","ms","String","topCanvas","pathsEnabled","CR","pathsImpld","path2dEnabled","./drawing-edges","./drawing-images","./drawing-label-text","./drawing-nodes","./drawing-redraw","./drawing-shapes","./export-image",71,"roundrectangle",72,"./base","./canvas",73,"NullRenderer",74,"Fabric","N","defN","navigator","hardwareConcurrency","cpus","err","fabfn","as","spreadSize","subsize","spread","runPs","runP","doneEarly","postpass","mapped","origResolve","oldLen","_$_$_fabmap","nothingInsdByResolve","incDatum","cmp","sortedSplit","_$_$_cmp","joined","eleI","eleJ","splitL","defineRandomPasser","arg1","threadFn","randomMap","reduce","reduceRight","terminate","halt","./thread","os",75,"defaultCmp","heapify","heappop","heappush","heappushpop","heapreplace","insort","nlargest","nsmallest","_siftdown","_siftup","lo","hi","mid","item","lastelt","returnitem","_ref","_i","_len","_ref1","_results","_results1","_j","elem","los","startpos","newitem","parentpos","childpos","endpos","rightpos","replace","pushpop","peek","contains","heap","insert","front","has","factory",76,"registerJquery","Stylesheet","version","jQuery","fabric","./extension","./fabric","./jquery-plugin","./stylesheet","./window",77,"typeofstr","typeofobj","typeoffn","typeofhtmlele","HTMLElement","instanceStr","defined","isArray","constructor","object","integer","nonemptyString","domElement","DocumentTouch","gecko","InstallTrigger","documentElement","webkit","webkitURL","chromium","chrome","khtml","vendor","khtmlEtc","userAgent","windows","appVersion","mac","linux","unix",78,"cyReg","$ele","$this",79,"sqDistance","qbezierPtAt","bb1","bb2","straightLineIntersections","topStartX","topStartY","topEndX","topEndY","finiteLinesIntersect","rightStartX","rightStartY","rightEndX","rightEndY","bottomStartX","bottomStartY","bottomEndX","bottomEndY","leftStartX","leftStartY","leftEndX","leftEndY","arcIntersections","topLeftCenterX","topLeftCenterY","intersectLineCircle","topRightCenterX","topRightCenterY","bottomRightCenterX","bottomRightCenterY","bottomLeftCenterX","bottomLeftCenterY","x3","y3","solveCubic","discriminant","dum1","term1","r13","acos","zeroThreshold","closestParam","curX","curY","distSquared","minDistanceSquared","offset","lineSq","hypSq","dotProduct","adjSq","up","basePoints","direction","transformedPoints","expandedLineSet","expandPolygon","joinLines","lineSet","currentLineStartX","currentLineStartY","currentLineEndX","currentLineEndY","nextLineStartX","nextLineStartY","nextLineEndX","nextLineEndY","vertices","pad","currentPointX","currentPointY","nextPointX","nextPointY","offsetLength","normalizedOffsetX","normalizedOffsetY","ellipseWradius","ellipseHradius","len","newLength","lenProportion","t1","t2","tMin","tMax","inRangeParams","nearIntersectionX","nearIntersectionY","farIntersectionX","farIntersectionY","findCircleNearPoint","farX","farY","displacementX","displacementY","unitDisplacementX","unitDisplacementY","findMaxSqDistanceToOrigin","maxSqDistance","x4","y4","infiniteLines","ua_t","ub_t","u_b","ua","ub","intersections","currentX","currentY","nextX","nextY","amount","lenRatio","sides","rotationRadians","sx","sy","increment","currentAngle",80,"STATE_PENDING","STATE_FULFILLED","STATE_REJECTED","api","executor","fulfillValue","rejectReason","onFulfilled","onRejected","proxy","fulfill","deliver","curr","resolver","execute","execute_handlers","handlers","func","setImmediate","method","TypeError","resolved","ps","resolveAll","rejectAll","vals","doneCount","isPromise",81,"onlyThisGroup","selectorText","invalid","newQuery","currentSubject","colonSelectors","meta","subject","child","descendant","tokens","metaChar","comparatorOp","boolOp","separator","variable","cleanMetaChars","str","RegExp","$1","original","ops","op","exprs","query","populate","valueIsString","exec","substring","operator","childQuery","descendantQuery","modifier","remaining","consumeExpr","expectation","expr","consumed","consumeWhitespace","check","selfn","queryMatches","allColonSelectorsMatch","allIdsMatch","actualId","allClassesMatch","operandsMatch","allDataMatches","fieldVal","fieldValue","fieldStr","valStr","caseInsensitive","notExpr","handledNotExpr","search","fieldTruthy","fieldUndefined","fieldRef","allMetaMatches","matchesAny","confirmRelations","selectorFunction","filteredCollection","clean","isValue","queryToString",82,"styfn","contextStyles","propDiffs","ie","cxtMeta","getContextMeta","cxtStyle","getContextStyle","app","applyContextStyle","diffProps","updateStyleHints","getPropertiesDiff","oldCxtKey","newCxtKey","dualCxtKey","addedProp","oldHasCxt","newHasCxt","cxtHasDiffed","cxtHasMappedProps","mappedProperties","laterCxtOverrides","laterCxt","hasLaterCxt","cxtKey","prevKey","styleCxtKey","contextSelectorMatches","diffPropNames","cxtStyles","hasCxt","styProp","retDiffProps","diffPropName","cxtProp","eleProp","retDiffProp","applyParsedProperty","bypassed","oWidth","wrap","wrapW","borderW","cpss","cpd","cpw","curve","sd","sw","styleKey","parsedProp","flatProp","propIsBypass","origProp","origPropIsBypass","deleteBypass","currentProp","printMappingErr","mapData","mapLayoutData","mapScratch","isLayout","isScratch","fieldMin","fieldMax","r1","valueMin","r2","valueMax","g1","g2","b1","b2","a1","a2","clr","calcValue","mapping","layoutData","flatPropVal","fnRetVal","propInStyle","isBypass","anyPrev","diffProp","initVal","prevProp","fromProp","toProp","initDt","transitioning",83,"specifiedProps","camel2dash","isColor","isMulti","mutiple","propertyNames",84,"getEmSizeInPixels","px","containerCss","propName","getComputedStyle","getPropertyValue",85,"isRenderedVal","styleProp","implicitUnits","isEle","propsObj",86,"addDefaultStylesheet","resetToDefault","selectorStr","mapVal","cssRule","currentSelectorIsCore","./apply","./bypass","./container","./get-for-ele","./json","./parse","./properties","./string-sheet",87,"applyFromJson","defaultLength",88,"propIsFlat","argHash","propCache","parseImpl","passedValue","alias","pointsTo","trim","multiple","evenMultiple","valArr","unitless","checkEnums","enums","en","unitsRegex","allowPercent","propList","propsStr","propsSplit","tuple","color2tuple","regexes","enumProp",89,"rgba","rgbaNoBackRefs","hsla","hslaNoBackRefs","hex3","hex6","mapArg","zeroOneNumber","nOneOneNumber","nonNegativeInt","numbers","bidirectionalSize","bidirectionalSizes","bgSize","bgWH","bgPos","bgRepeat","bgFit","bgClip","fontVariant","textDecoration","textWrap","textBackgroundShape","nodeShape","compoundIncludeLabels","textRotation","polygonPointList","aliases","arrowPrefixes","pointsToProp","aliasProp","text-events","text-valign","text-halign","text-outline-color","text-outline-width","text-outline-opacity","text-opacity","text-decoration","text-transform","text-wrap","text-max-width","text-background-color","text-background-opacity","text-border-opacity","text-border-width","text-border-style","text-border-color","text-background-shape","font-family","font-style","font-weight","font-size","min-zoomed-font-size","edge-text-rotation","z-index","overlay-opacity","overlay-color","overlay-padding","shadow-opacity","shadow-color","shadow-blur","shadow-offset-x","shadow-offset-y","text-shadow-opacity","text-shadow-color","text-shadow-blur","text-shadow-offset-x","text-shadow-offset-y","transition-property","transition-duration","transition-delay","transition-timing-function","background-blacken","background-color","background-opacity","background-image","background-image-opacity","background-position-x","background-position-y","background-repeat","background-fit","background-clip","background-width","background-height","border-color","border-opacity","border-width","border-style","shape-polygon-points","padding-top","padding-bottom","padding-left","padding-right","compound-sizing-wrt-labels","pie-size","line-style","line-color","control-point-step-size","control-point-weights","segment-weights","segment-distances","curve-style","haystack-radius","selection-box-color","selection-box-opacity","selection-box-border-color","selection-box-border-width","active-bg-color","active-bg-opacity","active-bg-size","outside-texture-bg-color","outside-texture-bg-opacity",90,"applyFromString","removeSelAndBlockFromRemaining","selAndBlockStr","substr","removePropAndValFromRem","blockRem","propAndValStr","nothingLeftToParse","selAndBlock","blockStr","invalidBlock","propAndVal","propStr",91,"sheetfn",92,"requires","files","thdfn","stringifyFieldVal","JSON","stringify","fnAsRequire","req","fnAs","protoreq","subname","protoNonempty","protoStr","hasOwnProperty","isPathStr","running","useWW","useNode","threadTechAlreadyExists","ran","fnImplStr","fnStr","wwifyFile","file","location","pathname","fnBlob","fnUrl","fnPre","Blob","URL","createObjectURL","ww","webworker","Worker","postMessage","$$eval","isObject","$$resolve","$$reject","fork","__dirname","send","promiseResolve","promiseReject","timer","eval","ls","kill","defineFnal","child_process",93,"hex2tuple","hex","shortHex","base","parseInt","hsl2tuple","hsl","hue2rgb","rgb2tuple","rgb","isPct","channel","atLeastOneIsPct","allArePct","colorname2tuple","colors","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen",94,"msg","trace","_staticEmptyObject","assign","memoize","../math","./colors","./maps","./memoize","./regex","./strings","./timing",95,"mapEmpty","pushMap","deleteMap","keepChildren","lastKey",96,"keyFn",97,98,"charAt",99,"performance","raf","mozRequestAnimationFrame","webkitRequestAnimationFrame","msRequestAnimationFrame","pnow","throttle","wait","leading","trailing","maxWait","maxTimeoutId","stamp","timeoutId","trailingCall","lastCalled","delayed","isCalled","maxDelayed","leadingCall",100],"mappings":"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","file":"cytoscape.min.js","sourcesContent":["'use strict';\n\nvar util = require('./util');\nvar is = require('./is');\nvar Promise = require('./promise');\n\nvar Animation = function( target, opts, opts2 ){\n  if( !(this instanceof Animation) ){\n    return new Animation( target, opts, opts2 );\n  }\n\n  var _p = this._private = util.extend( {\n    duration: 1000\n  }, opts, opts2 );\n\n  _p.target = target;\n  _p.style = _p.style || _p.css;\n  _p.started = false;\n  _p.playing = false;\n  _p.hooked = false;\n  _p.applying = false;\n  _p.progress = 0;\n  _p.completes = [];\n  _p.frames = [];\n\n  if( _p.complete && is.fn(_p.complete) ){\n    _p.completes.push( _p.complete );\n  }\n\n  // for future timeline/animations impl\n  this.length = 1;\n  this[0] = this;\n};\n\nvar anifn = Animation.prototype;\n\nutil.extend( anifn, {\n\n  instanceString: function(){ return 'animation'; },\n\n  hook: function(){\n    var _p = this._private;\n\n    if( !_p.hooked ){\n      // add to target's animation queue\n      var q;\n      var tAni = _p.target._private.animation;\n      if( _p.queue ){\n        q = tAni.queue;\n      } else {\n        q = tAni.current;\n      }\n      q.push( this );\n\n      // add to the animation loop pool\n      if( is.elementOrCollection( _p.target ) ){\n        _p.target.cy().addToAnimationPool( _p.target );\n      }\n\n      _p.hooked = true;\n    }\n\n    return this;\n  },\n\n  play: function(){\n    var _p = this._private;\n\n    // autorewind\n    if( _p.progress === 1 ){\n      _p.progress = 0;\n    }\n\n    _p.playing = true;\n    _p.started = false; // needs to be started by animation loop\n    _p.stopped = false;\n\n    this.hook();\n\n    // the animation loop will start the animation...\n\n    return this;\n  },\n\n  playing: function(){\n    return this._private.playing;\n  },\n\n  apply: function(){\n    var _p = this._private;\n\n    _p.applying = true;\n    _p.started = false; // needs to be started by animation loop\n    _p.stopped = false;\n\n    this.hook();\n\n    // the animation loop will apply the animation at this progress\n\n    return this;\n  },\n\n  applying: function(){\n    return this._private.applying;\n  },\n\n  pause: function(){\n    var _p = this._private;\n\n    _p.playing = false;\n    _p.started = false;\n\n    return this;\n  },\n\n  stop: function(){\n    var _p = this._private;\n\n    _p.playing = false;\n    _p.started = false;\n    _p.stopped = true; // to be removed from animation queues\n\n    return this;\n  },\n\n  rewind: function(){\n    return this.progress(0);\n  },\n\n  fastforward: function(){\n    return this.progress(1);\n  },\n\n  time: function( t ){\n    var _p = this._private;\n\n    if( t === undefined ){\n      return _p.progress * _p.duration;\n    } else {\n      return this.progress( t / _p.duration );\n    }\n  },\n\n  progress: function( p ){\n    var _p = this._private;\n    var wasPlaying = _p.playing;\n\n    if( p === undefined ){\n      return _p.progress;\n    } else {\n      if( wasPlaying ){\n        this.pause();\n      }\n\n      _p.progress = p;\n      _p.started = false;\n\n      if( wasPlaying ){\n        this.play();\n      }\n    }\n\n    return this;\n  },\n\n  completed: function(){\n    return this._private.progress === 1;\n  },\n\n  reverse: function(){\n    var _p = this._private;\n    var wasPlaying = _p.playing;\n\n    if( wasPlaying ){\n      this.pause();\n    }\n\n    _p.progress = 1 - _p.progress;\n    _p.started = false;\n\n    var swap = function( a, b ){\n      var _pa = _p[a];\n\n      _p[a] = _p[b];\n      _p[b] = _pa;\n    };\n\n    swap( 'zoom', 'startZoom' );\n    swap( 'pan', 'startPan' );\n    swap( 'position', 'startPosition' );\n\n    // swap styles\n    for( var i = 0; i < _p.style.length; i++ ){\n      var prop = _p.style[i];\n      var name = prop.name;\n      var startStyleProp = _p.startStyle[ name ];\n\n      _p.startStyle[ name ] = _p.startStyle[ util.dash2camel( name ) ] = prop;\n      _p.style[i] = startStyleProp;\n    }\n\n    if( wasPlaying ){\n      this.play();\n    }\n\n    return this;\n  },\n\n  promise: function( type ){\n    var _p = this._private;\n\n    var arr;\n\n    switch( type ){\n      case 'frame':\n        arr = _p.frames;\n        break;\n      default:\n      case 'complete':\n      case 'completed':\n        arr = _p.completes;\n    }\n\n    return new Promise(function( resolve, reject ){\n      arr.push(function(){\n        resolve();\n      });\n    });\n  }\n\n} );\n\nanifn.complete = anifn.completed;\n\nmodule.exports = Animation;\n","/*!\n * This file is part of Cytoscape.js 2.5.3.\n *\n * Cytoscape.js is free software: you can redistribute it and/or modify it\n * under the terms of the GNU Lesser General Public License as published by the Free\n * Software Foundation, either version 3 of the License, or (at your option) any\n * later version.\n *\n * Cytoscape.js is distributed in the hope that it will be useful, but WITHOUT\n * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more\n * details.\n *\n * You should have received a copy of the GNU Lesser General Public License along with\n * Cytoscape.js. If not, see <http://www.gnu.org/licenses/>.\n */\n\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.cytoscape = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('./util');\nvar is = _dereq_('./is');\nvar Promise = _dereq_('./promise');\n\nvar Animation = function( target, opts, opts2 ){\n  if( !(this instanceof Animation) ){\n    return new Animation( target, opts, opts2 );\n  }\n\n  var _p = this._private = util.extend( {\n    duration: 1000\n  }, opts, opts2 );\n\n  _p.target = target;\n  _p.style = _p.style || _p.css;\n  _p.started = false;\n  _p.playing = false;\n  _p.hooked = false;\n  _p.applying = false;\n  _p.progress = 0;\n  _p.completes = [];\n  _p.frames = [];\n\n  if( _p.complete && is.fn(_p.complete) ){\n    _p.completes.push( _p.complete );\n  }\n\n  // for future timeline/animations impl\n  this.length = 1;\n  this[0] = this;\n};\n\nvar anifn = Animation.prototype;\n\nutil.extend( anifn, {\n\n  instanceString: function(){ return 'animation'; },\n\n  hook: function(){\n    var _p = this._private;\n\n    if( !_p.hooked ){\n      // add to target's animation queue\n      var q;\n      var tAni = _p.target._private.animation;\n      if( _p.queue ){\n        q = tAni.queue;\n      } else {\n        q = tAni.current;\n      }\n      q.push( this );\n\n      // add to the animation loop pool\n      if( is.elementOrCollection( _p.target ) ){\n        _p.target.cy().addToAnimationPool( _p.target );\n      }\n\n      _p.hooked = true;\n    }\n\n    return this;\n  },\n\n  play: function(){\n    var _p = this._private;\n\n    // autorewind\n    if( _p.progress === 1 ){\n      _p.progress = 0;\n    }\n\n    _p.playing = true;\n    _p.started = false; // needs to be started by animation loop\n    _p.stopped = false;\n\n    this.hook();\n\n    // the animation loop will start the animation...\n\n    return this;\n  },\n\n  playing: function(){\n    return this._private.playing;\n  },\n\n  apply: function(){\n    var _p = this._private;\n\n    _p.applying = true;\n    _p.started = false; // needs to be started by animation loop\n    _p.stopped = false;\n\n    this.hook();\n\n    // the animation loop will apply the animation at this progress\n\n    return this;\n  },\n\n  applying: function(){\n    return this._private.applying;\n  },\n\n  pause: function(){\n    var _p = this._private;\n\n    _p.playing = false;\n    _p.started = false;\n\n    return this;\n  },\n\n  stop: function(){\n    var _p = this._private;\n\n    _p.playing = false;\n    _p.started = false;\n    _p.stopped = true; // to be removed from animation queues\n\n    return this;\n  },\n\n  rewind: function(){\n    return this.progress(0);\n  },\n\n  fastforward: function(){\n    return this.progress(1);\n  },\n\n  time: function( t ){\n    var _p = this._private;\n\n    if( t === undefined ){\n      return _p.progress * _p.duration;\n    } else {\n      return this.progress( t / _p.duration );\n    }\n  },\n\n  progress: function( p ){\n    var _p = this._private;\n    var wasPlaying = _p.playing;\n\n    if( p === undefined ){\n      return _p.progress;\n    } else {\n      if( wasPlaying ){\n        this.pause();\n      }\n\n      _p.progress = p;\n      _p.started = false;\n\n      if( wasPlaying ){\n        this.play();\n      }\n    }\n\n    return this;\n  },\n\n  completed: function(){\n    return this._private.progress === 1;\n  },\n\n  reverse: function(){\n    var _p = this._private;\n    var wasPlaying = _p.playing;\n\n    if( wasPlaying ){\n      this.pause();\n    }\n\n    _p.progress = 1 - _p.progress;\n    _p.started = false;\n\n    var swap = function( a, b ){\n      var _pa = _p[a];\n\n      _p[a] = _p[b];\n      _p[b] = _pa;\n    };\n\n    swap( 'zoom', 'startZoom' );\n    swap( 'pan', 'startPan' );\n    swap( 'position', 'startPosition' );\n\n    // swap styles\n    for( var i = 0; i < _p.style.length; i++ ){\n      var prop = _p.style[i];\n      var name = prop.name;\n      var startStyleProp = _p.startStyle[ name ];\n\n      _p.startStyle[ name ] = _p.startStyle[ util.dash2camel( name ) ] = prop;\n      _p.style[i] = startStyleProp;\n    }\n\n    if( wasPlaying ){\n      this.play();\n    }\n\n    return this;\n  },\n\n  promise: function( type ){\n    var _p = this._private;\n\n    var arr;\n\n    switch( type ){\n      case 'frame':\n        arr = _p.frames;\n        break;\n      default:\n      case 'complete':\n      case 'completed':\n        arr = _p.completes;\n    }\n\n    return new Promise(function( resolve, reject ){\n      arr.push(function(){\n        resolve();\n      });\n    });\n  }\n\n} );\n\nanifn.complete = anifn.completed;\n\nmodule.exports = Animation;\n\n},{\"./is\":77,\"./promise\":80,\"./util\":94}],2:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\n\nvar elesfn = ({\n\n  // Implemented from pseudocode from wikipedia\n  aStar: function(options) {\n    var eles = this;\n\n    options = options || {};\n\n    // Reconstructs the path from Start to End, acumulating the result in pathAcum\n    var reconstructPath = function(start, end, cameFromMap, pathAcum) {\n      // Base case\n      if (start == end) {\n        pathAcum.push( cy.getElementById(end) );\n        return pathAcum;\n      }\n\n      if (end in cameFromMap) {\n        // We know which node is before the last one\n        var previous = cameFromMap[end];\n        var previousEdge = cameFromEdge[end];\n\n        pathAcum.push( cy.getElementById(end) );\n        pathAcum.push( cy.getElementById(previousEdge) );\n\n\n        return reconstructPath(start,\n                     previous,\n                     cameFromMap,\n                     pathAcum);\n      }\n\n      // We should not reach here!\n      return undefined;\n    };\n\n    // Returns the index of the element in openSet which has minimum fScore\n    var findMin = function(openSet, fScore) {\n      if (openSet.length === 0) {\n        // Should never be the case\n        return undefined;\n      }\n      var minPos = 0;\n      var tempScore = fScore[openSet[0]];\n      for (var i = 1; i < openSet.length; i++) {\n        var s = fScore[openSet[i]];\n        if (s < tempScore) {\n          tempScore = s;\n          minPos = i;\n        }\n      }\n      return minPos;\n    };\n\n    var cy = this._private.cy;\n\n    // root - mandatory!\n    if (options != null && options.root != null) {\n      var source = is.string(options.root) ?\n        // use it as a selector, e.g. \"#rootID\n        this.filter(options.root)[0] :\n        options.root[0];\n    } else {\n      return undefined;\n    }\n\n    // goal - mandatory!\n    if (options.goal != null) {\n      var target = is.string(options.goal) ?\n        // use it as a selector, e.g. \"#goalID\n        this.filter(options.goal)[0] :\n        options.goal[0];\n    } else {\n      return undefined;\n    }\n\n    // Heuristic function - optional\n    if (options.heuristic != null && is.fn(options.heuristic)) {\n      var heuristic = options.heuristic;\n    } else {\n      var heuristic = function(){ return 0; }; // use constant if unspecified\n    }\n\n    // Weight function - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var closedSet = [];\n    var openSet = [source.id()];\n    var cameFrom = {};\n    var cameFromEdge = {};\n    var gScore = {};\n    var fScore = {};\n\n    gScore[source.id()] = 0;\n    fScore[source.id()] = heuristic(source);\n\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n\n    // Counter\n    var steps = 0;\n\n    // Main loop\n    while (openSet.length > 0) {\n      var minPos = findMin(openSet, fScore);\n      var cMin = cy.getElementById( openSet[minPos] );\n      steps++;\n\n      // If we've found our goal, then we are done\n      if (cMin.id() == target.id()) {\n        var rPath = reconstructPath(source.id(), target.id(), cameFrom, []);\n        rPath.reverse();\n        return {\n          found : true,\n          distance : gScore[cMin.id()],\n          path : eles.spawn(rPath),\n          steps : steps\n        };\n      }\n\n      // Add cMin to processed nodes\n      closedSet.push(cMin.id());\n      // Remove cMin from boundary nodes\n      openSet.splice(minPos, 1);\n\n      // Update scores for neighbors of cMin\n      // Take into account if graph is directed or not\n      var vwEdges = cMin.connectedEdges();\n      if( directed ){ vwEdges = vwEdges.stdFilter(function(ele){ return ele.data('source') === cMin.id(); }); }\n      vwEdges = vwEdges.intersect(edges);\n\n      for (var i = 0; i < vwEdges.length; i++) {\n        var e = vwEdges[i];\n        var w = e.connectedNodes().stdFilter(function(n){ return n.id() !== cMin.id(); }).intersect(nodes);\n\n        // if node is in closedSet, ignore it\n        if (closedSet.indexOf(w.id()) != -1) {\n          continue;\n        }\n\n        // New tentative score for node w\n        var tempScore = gScore[cMin.id()] + weightFn.apply(e, [e]);\n\n        // Update gScore for node w if:\n        //   w not present in openSet\n        // OR\n        //   tentative gScore is less than previous value\n\n        // w not in openSet\n        if (openSet.indexOf(w.id()) == -1) {\n          gScore[w.id()] = tempScore;\n          fScore[w.id()] = tempScore + heuristic(w);\n          openSet.push(w.id()); // Add node to openSet\n          cameFrom[w.id()] = cMin.id();\n          cameFromEdge[w.id()] = e.id();\n          continue;\n        }\n        // w already in openSet, but with greater gScore\n        if (tempScore < gScore[w.id()]) {\n          gScore[w.id()] = tempScore;\n          fScore[w.id()] = tempScore + heuristic(w);\n          cameFrom[w.id()] = cMin.id();\n        }\n\n      } // End of neighbors update\n\n    } // End of main loop\n\n    // If we've reached here, then we've not reached our goal\n    return {\n      found : false,\n      distance : undefined,\n      path : undefined,\n      steps : steps\n    };\n  }\n\n}); // elesfn\n\n\nmodule.exports = elesfn;\n\n},{\"../../is\":77}],3:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\nvar util = _dereq_('../../util');\n\nvar elesfn = ({\n\n  // Implemented from pseudocode from wikipedia\n  bellmanFord: function(options) {\n    var eles = this;\n\n    options = options || {};\n\n    // Weight function - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    // root - mandatory!\n    if (options.root != null) {\n      if (is.string(options.root)) {\n        // use it as a selector, e.g. \"#rootID\n        var source = this.filter(options.root)[0];\n      } else {\n        var source = options.root[0];\n      }\n    } else {\n      return undefined;\n    }\n\n    var cy = this._private.cy;\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n\n    // mapping: node id -> position in nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Initializations\n    var cost = [];\n    var predecessor = [];\n    var predEdge = [];\n\n    for (var i = 0; i < numNodes; i++) {\n      if (nodes[i].id() === source.id()) {\n        cost[i] = 0;\n      } else {\n        cost[i] = Infinity;\n      }\n      predecessor[i] = undefined;\n    }\n\n    // Edges relaxation\n    var flag = false;\n    for (var i = 1; i < numNodes; i++) {\n      flag = false;\n      for (var e = 0; e < edges.length; e++) {\n        var sourceIndex = id2position[edges[e].source().id()];\n        var targetIndex = id2position[edges[e].target().id()];\n        var weight = weightFn.apply(edges[e], [edges[e]]);\n\n        var temp = cost[sourceIndex] + weight;\n        if (temp < cost[targetIndex]) {\n          cost[targetIndex] = temp;\n          predecessor[targetIndex] = sourceIndex;\n          predEdge[targetIndex] = edges[e];\n          flag = true;\n        }\n\n        // If undirected graph, we need to take into account the 'reverse' edge\n        if (!directed) {\n          var temp = cost[targetIndex] + weight;\n          if (temp < cost[sourceIndex]) {\n            cost[sourceIndex] = temp;\n            predecessor[sourceIndex] = targetIndex;\n            predEdge[sourceIndex] = edges[e];\n            flag = true;\n          }\n        }\n      }\n\n      if (!flag) {\n        break;\n      }\n    }\n\n    if (flag) {\n      // Check for negative weight cycles\n      for (var e = 0; e < edges.length; e++) {\n        var sourceIndex = id2position[edges[e].source().id()];\n        var targetIndex = id2position[edges[e].target().id()];\n        var weight = weightFn.apply(edges[e], [edges[e]]);\n\n        if (cost[sourceIndex] + weight < cost[targetIndex]) {\n          util.error(\"Graph contains a negative weight cycle for Bellman-Ford\");\n          return { pathTo: undefined,\n               distanceTo: undefined,\n               hasNegativeWeightCycle: true};\n        }\n      }\n    }\n\n    // Build result object\n    var position2id = [];\n    for (var i = 0; i < numNodes; i++) {\n      position2id.push(nodes[i].id());\n    }\n\n\n    var res = {\n      distanceTo : function(to) {\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n\n        return cost[id2position[toId]];\n      },\n\n      pathTo : function(to) {\n\n        var reconstructPathAux = function(predecessor, fromPos, toPos, position2id, acumPath, predEdge) {\n          for(;;){\n            // Add toId to path\n            acumPath.push( cy.getElementById(position2id[toPos]) );\n            acumPath.push( predEdge[toPos] );\n\n            if (fromPos === toPos) {\n              // reached starting node\n              return acumPath;\n            }\n\n            // If no path exists, discart acumulated path and return undefined\n            var predPos = predecessor[toPos];\n            if (typeof predPos === \"undefined\") {\n              return undefined;\n            }\n\n            toPos = predPos;\n          }\n\n        };\n\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n        var path = [];\n\n        // This returns a reversed path\n        var res =  reconstructPathAux(predecessor,\n                      id2position[source.id()],\n                      id2position[toId],\n                      position2id,\n                      path,\n                      predEdge);\n\n        // Get it in the correct order and return it\n        if (res != null) {\n          res.reverse();\n        }\n\n        return eles.spawn(res);\n      },\n\n      hasNegativeWeightCycle: false\n    };\n\n    return res;\n\n  } // bellmanFord\n\n}); // elesfn\n\nmodule.exports = elesfn;\n\n},{\"../../is\":77,\"../../util\":94}],4:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\n\nvar elesfn = ({\n\n  // Implemented from the algorithm in the paper \"On Variants of Shortest-Path Betweenness Centrality and their Generic Computation\" by Ulrik Brandes\n  betweennessCentrality: function (options) {\n    options = options || {};\n\n    // Weight - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n      var weighted = true;\n    } else {\n      var weighted = false;\n    }\n\n    // Directed - default false\n    if (options.directed != null && is.bool(options.directed)) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var priorityInsert = function (queue, ele) {\n      queue.unshift(ele);\n      for (var i = 0; d[queue[i]] < d[queue[i + 1]] && i < queue.length - 1; i++) {\n        var tmp = queue[i];\n        queue[i] = queue[i + 1];\n        queue[i + 1] = tmp;\n      }\n    };\n\n    var cy = this._private.cy;\n\n    // starting\n    var V = this.nodes();\n    var A = {};\n    var C = {};\n\n    // A contains the neighborhoods of every node\n    for (var i = 0; i < V.length; i++) {\n      if (directed) {\n        A[V[i].id()] = V[i].outgoers(\"node\"); // get outgoers of every node\n      } else {\n        A[V[i].id()] = V[i].openNeighborhood(\"node\"); // get neighbors of every node\n      }\n    }\n\n    // C contains the betweenness values\n    for (var i = 0; i < V.length; i++) {\n      C[V[i].id()] = 0;\n    }\n\n    for (var s = 0; s < V.length; s++) {\n      var S = []; // stack\n      var P = {};\n      var g = {};\n      var d = {};\n      var Q = []; // queue\n\n      // init dictionaries\n      for (var i = 0; i < V.length; i++) {\n        P[V[i].id()] = [];\n        g[V[i].id()] = 0;\n        d[V[i].id()] = Number.POSITIVE_INFINITY;\n      }\n\n      g[V[s].id()] = 1; // sigma\n      d[V[s].id()] = 0; // distance to s\n\n      Q.unshift(V[s].id());\n\n      while (Q.length > 0) {\n        var v = Q.pop();\n        S.push(v);\n        if (weighted) {\n          A[v].forEach(function (w) {\n            if (cy.$('#' + v).edgesTo(w).length > 0) {\n              var edge = cy.$('#' + v).edgesTo(w)[0];\n            } else {\n              var edge = w.edgesTo('#' + v)[0];\n            }\n\n            var edgeWeight = weightFn.apply(edge, [edge]);\n\n            if (d[w.id()] > d[v] + edgeWeight) {\n              d[w.id()] = d[v] + edgeWeight;\n              if (Q.indexOf(w.id()) < 0) { //if w is not in Q\n                priorityInsert(Q, w.id());\n              } else { // update position if w is in Q\n                Q.splice(Q.indexOf(w.id()), 1);\n                priorityInsert(Q, w.id());\n              }\n              g[w.id()] = 0;\n              P[w.id()] = [];\n            }\n            if (d[w.id()] == d[v] + edgeWeight) {\n              g[w.id()] = g[w.id()] + g[v];\n              P[w.id()].push(v);\n            }\n          });\n        } else {\n          A[v].forEach(function (w) {\n            if (d[w.id()] == Number.POSITIVE_INFINITY) {\n              Q.unshift(w.id());\n              d[w.id()] = d[v] + 1;\n            }\n            if (d[w.id()] == d[v] + 1) {\n              g[w.id()] = g[w.id()] + g[v];\n              P[w.id()].push(v);\n            }\n          });\n        }\n      }\n\n      var e = {};\n      for (var i = 0; i < V.length; i++) {\n        e[V[i].id()] = 0;\n      }\n\n      while (S.length > 0) {\n        var w = S.pop();\n        P[w].forEach(function (v) {\n          e[v] = e[v] + (g[v] / g[w]) * (1 + e[w]);\n          if (w != V[s].id())\n            C[w] = C[w] + e[w];\n        });\n      }\n    }\n\n    var max = 0;\n    for (var key in C) {\n      if (max < C[key])\n        max = C[key];\n    }\n\n    var ret = {\n      betweenness: function (node) {\n        if (is.string(node)) {\n          var node = (cy.filter(node)[0]).id();\n        } else {\n          var node = node.id();\n        }\n\n        return C[node];\n      },\n\n      betweennessNormalized: function (node) {\n        if (is.string(node)) {\n          var node = (cy.filter(node)[0]).id();\n        } else {\n          var node = node.id();\n        }\n\n        return C[node] / max;\n      }\n    };\n\n    // alias\n    ret.betweennessNormalised = ret.betweennessNormalized;\n\n    return ret;\n  } // betweennessCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.bc = elesfn.betweennessCentrality;\n\nmodule.exports = elesfn;\n\n},{\"../../is\":77}],5:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\nvar Heap = _dereq_('../../heap');\n\nvar defineSearch = function( params ){\n  params = {\n    bfs: params.bfs || !params.dfs,\n    dfs: params.dfs || !params.bfs\n  };\n\n  // from pseudocode on wikipedia\n  return function searchFn( roots, fn, directed ){\n    var options;\n    var std;\n    var thisArg;\n    if( is.plainObject(roots) && !is.elementOrCollection(roots) ){\n      options = roots;\n      roots = options.roots || options.root;\n      fn = options.visit;\n      directed = options.directed;\n      std = options.std;\n      thisArg = options.thisArg;\n    }\n\n    directed = arguments.length === 2 && !is.fn(fn) ? fn : directed;\n    fn = is.fn(fn) ? fn : function(){};\n\n    var cy = this._private.cy;\n    var v = roots = is.string(roots) ? this.filter(roots) : roots;\n    var Q = [];\n    var connectedNodes = [];\n    var connectedBy = {};\n    var id2depth = {};\n    var V = {};\n    var j = 0;\n    var found;\n    var nodes = this.nodes();\n    var edges = this.edges();\n\n    // enqueue v\n    for( var i = 0; i < v.length; i++ ){\n      if( v[i].isNode() ){\n        Q.unshift( v[i] );\n\n        if( params.bfs ){\n          V[ v[i].id() ] = true;\n\n          connectedNodes.push( v[i] );\n        }\n\n        id2depth[ v[i].id() ] = 0;\n      }\n    }\n\n    while( Q.length !== 0 ){\n      var v = params.bfs ? Q.shift() : Q.pop();\n\n      if( params.dfs ){\n        if( V[ v.id() ] ){ continue; }\n\n        V[ v.id() ] = true;\n\n        connectedNodes.push( v );\n      }\n\n      var depth = id2depth[ v.id() ];\n      var prevEdge = connectedBy[ v.id() ];\n      var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not( v )[0];\n      var ret;\n\n      if( std ){\n        ret = fn.call(thisArg, v, prevEdge, prevNode, j++, depth);\n      } else {\n        ret = fn.call(v, j++, depth, v, prevEdge, prevNode);\n      }\n\n      if( ret === true ){\n        found = v;\n        break;\n      }\n\n      if( ret === false ){\n        break;\n      }\n\n      var vwEdges = v.connectedEdges(directed ? function(){ return this.data('source') === v.id(); } : undefined).intersect( edges );\n      for( var i = 0; i < vwEdges.length; i++ ){\n        var e = vwEdges[i];\n        var w = e.connectedNodes(function(){ return this.id() !== v.id(); }).intersect( nodes );\n\n        if( w.length !== 0 && !V[ w.id() ] ){\n          w = w[0];\n\n          Q.push( w );\n\n          if( params.bfs ){\n            V[ w.id() ] = true;\n\n            connectedNodes.push( w );\n          }\n\n          connectedBy[ w.id() ] = e;\n\n          id2depth[ w.id() ] = id2depth[ v.id() ] + 1;\n        }\n      }\n\n    }\n\n    var connectedEles = [];\n\n    for( var i = 0; i < connectedNodes.length; i++ ){\n      var node = connectedNodes[i];\n      var edge = connectedBy[ node.id() ];\n\n      if( edge ){\n        connectedEles.push( edge );\n      }\n\n      connectedEles.push( node );\n    }\n\n    return {\n      path: cy.collection( connectedEles, { unique: true } ),\n      found: cy.collection( found )\n    };\n  };\n};\n\n// search, spanning trees, etc\nvar elesfn = ({\n\n  breadthFirstSearch: defineSearch({ bfs: true }),\n  depthFirstSearch: defineSearch({ dfs: true }),\n\n  // kruskal's algorithm (finds min spanning tree, assuming undirected graph)\n  // implemented from pseudocode from wikipedia\n  kruskal: function( weightFn ){\n    var cy = this.cy();\n\n    weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)\n\n    function findSet(ele){\n      for( var i = 0; i < forest.length; i++ ){\n        var eles = forest[i];\n\n        if( eles.anySame(ele) ){\n          return {\n            eles: eles,\n            index: i\n          };\n        }\n      }\n    }\n\n    var A = cy.collection(cy, []);\n    var forest = [];\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){\n      forest.push( nodes[i].collection() );\n    }\n\n    var edges = this.edges();\n    var S = edges.toArray().sort(function(a, b){\n      var weightA = weightFn.call(a, a);\n      var weightB = weightFn.call(b, b);\n\n      return weightA - weightB;\n    });\n\n    for(var i = 0; i < S.length; i++){\n      var edge = S[i];\n      var u = edge.source()[0];\n      var v = edge.target()[0];\n      var setU = findSet(u);\n      var setV = findSet(v);\n\n      if( setU.index !== setV.index ){\n        A = A.add( edge );\n\n        // combine forests for u and v\n        forest[ setU.index ] = setU.eles.add( setV.eles );\n        forest.splice( setV.index, 1 );\n      }\n    }\n\n    return nodes.add( A );\n\n  },\n\n  dijkstra: function( root, weightFn, directed ){\n    var options;\n    if( is.plainObject(root) && !is.elementOrCollection(root) ){\n      options = root;\n      root = options.root;\n      weightFn = options.weight;\n      directed = options.directed;\n    }\n\n    var cy = this._private.cy;\n    weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)\n\n    var source = is.string(root) ? this.filter(root)[0] : root[0];\n    var dist = {};\n    var prev = {};\n    var knownDist = {};\n\n    var edges = this.edges().filter(function(){ return !this.isLoop(); });\n    var nodes = this.nodes();\n\n    var getDist = function(node){\n      return dist[ node.id() ];\n    };\n\n    var setDist = function(node, d){\n      dist[ node.id() ] = d;\n\n      Q.updateItem( node );\n    };\n\n    var Q = new Heap(function( a, b ){\n      return getDist(a) - getDist(b);\n    });\n\n    for( var i = 0; i < nodes.length; i++ ){\n      var node = nodes[i];\n\n      dist[ node.id() ] = node.same( source ) ? 0 : Infinity;\n      Q.push( node );\n    }\n\n    var distBetween = function(u, v){\n      var uvs = ( directed ? u.edgesTo(v) : u.edgesWith(v) ).intersect(edges);\n      var smallestDistance = Infinity;\n      var smallestEdge;\n\n      for( var i = 0; i < uvs.length; i++ ){\n        var edge = uvs[i];\n        var weight = weightFn.apply( edge, [edge] );\n\n        if( weight < smallestDistance || !smallestEdge ){\n          smallestDistance = weight;\n          smallestEdge = edge;\n        }\n      }\n\n      return {\n        edge: smallestEdge,\n        dist: smallestDistance\n      };\n    };\n\n    while( Q.size() > 0 ){\n      var u = Q.pop();\n      var smalletsDist = getDist(u);\n      var uid = u.id();\n\n      knownDist[uid] = smalletsDist;\n\n      if( smalletsDist === Math.Infinite ){\n        break;\n      }\n\n      var neighbors = u.neighborhood().intersect(nodes);\n      for( var i = 0; i < neighbors.length; i++ ){\n        var v = neighbors[i];\n        var vid = v.id();\n        var vDist = distBetween(u, v);\n\n        var alt = smalletsDist + vDist.dist;\n\n        if( alt < getDist(v) ){\n          setDist(v, alt);\n\n          prev[ vid ] = {\n            node: u,\n            edge: vDist.edge\n          };\n        }\n      } // for\n    } // while\n\n    return {\n      distanceTo: function(node){\n        var target = is.string(node) ? nodes.filter(node)[0] : node[0];\n\n        return knownDist[ target.id() ];\n      },\n\n      pathTo: function(node){\n        var target = is.string(node) ? nodes.filter(node)[0] : node[0];\n        var S = [];\n        var u = target;\n\n        if( target.length > 0 ){\n          S.unshift( target );\n\n          while( prev[ u.id() ] ){\n            var p = prev[ u.id() ];\n\n            S.unshift( p.edge );\n            S.unshift( p.node );\n\n            u = p.node;\n          }\n        }\n\n        return cy.collection( S );\n      }\n    };\n  }\n});\n\n// nice, short mathemathical alias\nelesfn.bfs = elesfn.breadthFirstSearch;\nelesfn.dfs = elesfn.depthFirstSearch;\n\nmodule.exports = elesfn;\n\n},{\"../../heap\":75,\"../../is\":77}],6:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\n\nvar elesfn = ({\n\n  closenessCentralityNormalized: function (options) {\n    options = options || {};\n\n    var cy = this.cy();\n\n    var harmonic = options.harmonic;\n    if( harmonic === undefined ){\n      harmonic = true;\n    }\n\n    var closenesses = {};\n    var maxCloseness = 0;\n    var nodes = this.nodes();\n    var fw = this.floydWarshall({ weight: options.weight, directed: options.directed });\n\n    // Compute closeness for every node and find the maximum closeness\n    for(var i = 0; i < nodes.length; i++){\n      var currCloseness = 0;\n      for (var j = 0; j < nodes.length; j++) {\n        if (i != j) {\n          var d = fw.distance(nodes[i], nodes[j]);\n\n          if( harmonic ){\n            currCloseness += 1 / d;\n          } else {\n            currCloseness += d;\n          }\n        }\n      }\n\n      if( !harmonic ){\n        currCloseness = 1 / currCloseness;\n      }\n\n      if (maxCloseness < currCloseness){\n        maxCloseness = currCloseness;\n      }\n\n      closenesses[nodes[i].id()] = currCloseness;\n    }\n\n    return {\n      closeness: function (node) {\n        if (is.string(node)) {\n          // from is a selector string\n          var node = (cy.filter(node)[0]).id();\n        } else {\n          // from is a node\n          var node = node.id();\n        }\n\n        return closenesses[node] / maxCloseness;\n      }\n    };\n  },\n\n  // Implemented from pseudocode from wikipedia\n  closenessCentrality: function (options) {\n    options = options || {};\n\n    // root - mandatory!\n    if (options.root != null) {\n      if (is.string(options.root)) {\n        // use it as a selector, e.g. \"#rootID\n        var root = this.filter(options.root)[0];\n      } else {\n        var root = options.root[0];\n      }\n    } else {\n      return undefined;\n    }\n\n    // weight - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weight = options.weight;\n    } else {\n      var weight = function(){return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null && is.bool(options.directed)) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var harmonic = options.harmonic;\n    if( harmonic === undefined ){\n      harmonic = true;\n    }\n\n    // we need distance from this node to every other node\n    var dijkstra = this.dijkstra({\n      root: root,\n      weight: weight,\n      directed: directed\n    });\n    var totalDistance = 0;\n\n    var nodes = this.nodes();\n    for (var i = 0; i < nodes.length; i++){\n      if (nodes[i].id() != root.id()){\n        var d = dijkstra.distanceTo(nodes[i]);\n\n        if( harmonic ){\n          totalDistance += 1 / d;\n        } else {\n          totalDistance += d;\n        }\n      }\n    }\n\n    return harmonic ? totalDistance : 1 / totalDistance;\n  } // closenessCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.cc = elesfn.closenessCentrality;\nelesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized;\n\nmodule.exports = elesfn;\n\n},{\"../../is\":77}],7:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\nvar util = _dereq_('../../util');\n\nvar elesfn = ({\n\n  degreeCentralityNormalized: function (options) {\n    options = options || {};\n\n    var cy = this.cy();\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n\n    if (!directed) {\n      var degrees = {};\n      var maxDegree = 0;\n\n      for (var i = 0; i < numNodes; i++) {\n        var node = nodes[i];\n        // add current node to the current options object and call degreeCentrality\n        var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));\n        if (maxDegree < currDegree.degree)\n          maxDegree = currDegree.degree;\n\n        degrees[node.id()] = currDegree.degree;\n      }\n\n      return {\n        degree: function (node) {\n          if (is.string(node)) {\n            // from is a selector string\n            var node = (cy.filter(node)[0]).id();\n          } else {\n            // from is a node\n            var node = node.id();\n          }\n\n          return degrees[node] / maxDegree;\n        }\n      };\n    } else {\n      var indegrees = {};\n      var outdegrees = {};\n      var maxIndegree = 0;\n      var maxOutdegree = 0;\n\n      for (var i = 0; i < numNodes; i++) {\n        var node = nodes[i];\n        // add current node to the current options object and call degreeCentrality\n        var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));\n\n        if (maxIndegree < currDegree.indegree)\n          maxIndegree = currDegree.indegree;\n\n        if (maxOutdegree < currDegree.outdegree)\n          maxOutdegree = currDegree.outdegree;\n\n        indegrees[node.id()] = currDegree.indegree;\n        outdegrees[node.id()] = currDegree.outdegree;\n      }\n\n      return {\n        indegree: function (node) {\n          if (is.string(node)) {\n            // from is a selector string\n            var node = (cy.filter(node)[0]).id();\n          } else {\n            // from is a node\n            var node = node.id();\n          }\n\n          return indegrees[node] / maxIndegree;\n        },\n        outdegree: function (node) {\n          if (is.string(node)) {\n            // from is a selector string\n            var node = (cy.filter(node)[0]).id();\n          } else {\n            // from is a node\n            var node = node.id();\n          }\n\n          return outdegrees[node] / maxOutdegree;\n        }\n\n      };\n    }\n\n  }, // degreeCentralityNormalized\n\n  // Implemented from the algorithm in Opsahl's paper\n  // \"Node centrality in weighted networks: Generalizing degree and shortest paths\"\n  // check the heading 2 \"Degree\"\n  degreeCentrality: function (options) {\n    options = options || {};\n\n    var callingEles = this;\n\n    // root - mandatory!\n    if (options != null && options.root != null) {\n      var root = is.string(options.root) ? this.filter(options.root)[0] : options.root[0];\n    } else {\n      return undefined;\n    }\n\n    // weight - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function (e) {\n        return 1;\n      };\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    // alpha - optional\n    if (options.alpha != null && is.number(options.alpha)) {\n      var alpha = options.alpha;\n    } else {\n      alpha = 0;\n    }\n\n\n    if (!directed) {\n      var connEdges = root.connectedEdges().intersection( callingEles );\n      var k = connEdges.length;\n      var s = 0;\n\n      // Now, sum edge weights\n      for (var i = 0; i < connEdges.length; i++) {\n        var edge = connEdges[i];\n        s += weightFn.apply(edge, [edge]);\n      }\n\n      return {\n        degree: Math.pow(k, 1 - alpha) * Math.pow(s, alpha)\n      };\n    } else {\n      var incoming = root.connectedEdges('edge[target = \"' + root.id() + '\"]').intersection( callingEles );\n      var outgoing = root.connectedEdges('edge[source = \"' + root.id() + '\"]').intersection( callingEles );\n      var k_in = incoming.length;\n      var k_out = outgoing.length;\n      var s_in = 0;\n      var s_out = 0;\n\n      // Now, sum incoming edge weights\n      for (var i = 0; i < incoming.length; i++) {\n        var edge = incoming[i];\n        s_in += weightFn.apply(edge, [edge]);\n      }\n\n      // Now, sum outgoing edge weights\n      for (var i = 0; i < outgoing.length; i++) {\n        var edge = outgoing[i];\n        s_out += weightFn.apply(edge, [edge]);\n      }\n\n      return {\n        indegree: Math.pow(k_in, 1 - alpha) * Math.pow(s_in, alpha),\n        outdegree: Math.pow(k_out, 1 - alpha) * Math.pow(s_out, alpha)\n      };\n    }\n  } // degreeCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.dc = elesfn.degreeCentrality;\nelesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized;\n\nmodule.exports = elesfn;\n\n},{\"../../is\":77,\"../../util\":94}],8:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\n\nvar elesfn = ({\n\n  // Implemented from pseudocode from wikipedia\n  floydWarshall: function(options) {\n    options = options || {};\n\n    var cy = this.cy();\n\n    // Weight function - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n\n    // mapping: node id -> position in nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Initialize distance matrix\n    var dist = [];\n    for (var i = 0; i < numNodes; i++) {\n      var newRow = new Array(numNodes);\n      for (var j = 0; j < numNodes; j++) {\n        if (i == j) {\n          newRow[j] = 0;\n        } else {\n          newRow[j] = Infinity;\n        }\n      }\n      dist.push(newRow);\n    }\n\n    // Initialize matrix used for path reconstruction\n    // Initialize distance matrix\n    var next = [];\n    var edgeNext = [];\n\n    var initMatrix = function(next){\n      for (var i = 0; i < numNodes; i++) {\n        var newRow = new Array(numNodes);\n        for (var j = 0; j < numNodes; j++) {\n          newRow[j] = undefined;\n        }\n        next.push(newRow);\n      }\n    };\n\n    initMatrix(next);\n    initMatrix(edgeNext);\n\n    // Process edges\n    for (var i = 0; i < edges.length ; i++) {\n      var sourceIndex = id2position[edges[i].source().id()];\n      var targetIndex = id2position[edges[i].target().id()];\n      var weight = weightFn.apply(edges[i], [edges[i]]);\n\n      // Check if already process another edge between same 2 nodes\n      if (dist[sourceIndex][targetIndex] > weight) {\n        dist[sourceIndex][targetIndex] = weight;\n        next[sourceIndex][targetIndex] = targetIndex;\n        edgeNext[sourceIndex][targetIndex] = edges[i];\n      }\n    }\n\n    // If undirected graph, process 'reversed' edges\n    if (!directed) {\n      for (var i = 0; i < edges.length ; i++) {\n        var sourceIndex = id2position[edges[i].target().id()];\n        var targetIndex = id2position[edges[i].source().id()];\n        var weight = weightFn.apply(edges[i], [edges[i]]);\n\n        // Check if already process another edge between same 2 nodes\n        if (dist[sourceIndex][targetIndex] > weight) {\n          dist[sourceIndex][targetIndex] = weight;\n          next[sourceIndex][targetIndex] = targetIndex;\n          edgeNext[sourceIndex][targetIndex] = edges[i];\n        }\n      }\n    }\n\n    // Main loop\n    for (var k = 0; k < numNodes; k++) {\n      for (var i = 0; i < numNodes; i++) {\n        for (var j = 0; j < numNodes; j++) {\n          if (dist[i][k] + dist[k][j] < dist[i][j]) {\n            dist[i][j] = dist[i][k] + dist[k][j];\n            next[i][j] = next[i][k];\n          }\n        }\n      }\n    }\n\n    // Build result object\n    var position2id = [];\n    for (var i = 0; i < numNodes; i++) {\n      position2id.push(nodes[i].id());\n    }\n\n    var res = {\n      distance: function(from, to) {\n        if (is.string(from)) {\n          // from is a selector string\n          var fromId = (cy.filter(from)[0]).id();\n        } else {\n          // from is a node\n          var fromId = from.id();\n        }\n\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n\n        return dist[id2position[fromId]][id2position[toId]];\n      },\n\n      path: function(from, to) {\n        var reconstructPathAux = function(from, to, next, position2id, edgeNext) {\n          if (from === to) {\n            return cy.getElementById( position2id[from] );\n          }\n          if (next[from][to] === undefined) {\n            return undefined;\n          }\n\n          var path = [ cy.getElementById(position2id[from]) ];\n          var prev = from;\n          while (from !== to) {\n            prev = from;\n            from = next[from][to];\n\n            var edge = edgeNext[prev][from];\n            path.push( edge );\n\n            path.push( cy.getElementById(position2id[from]) );\n          }\n          return path;\n        };\n\n        if (is.string(from)) {\n          // from is a selector string\n          var fromId = (cy.filter(from)[0]).id();\n        } else {\n          // from is a node\n          var fromId = from.id();\n        }\n\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n\n        var pathArr = reconstructPathAux(id2position[fromId],\n                      id2position[toId],\n                      next,\n                      position2id,\n                      edgeNext);\n\n        return cy.collection( pathArr );\n      }\n    };\n\n    return res;\n\n  } // floydWarshall\n\n}); // elesfn\n\nmodule.exports = elesfn;\n\n},{\"../../is\":77}],9:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\n\nvar elesfn = {};\n\n[\n  _dereq_('./bfs-dfs'),\n  _dereq_('./a-star'),\n  _dereq_('./floyd-warshall'),\n  _dereq_('./bellman-ford'),\n  _dereq_('./kerger-stein'),\n  _dereq_('./page-rank'),\n  _dereq_('./degree-centrality'),\n  _dereq_('./closeness-centrality'),\n  _dereq_('./betweenness-centrality')\n].forEach(function( props ){\n  util.extend( elesfn, props );\n});\n\nmodule.exports = elesfn;\n\n},{\"../../util\":94,\"./a-star\":2,\"./bellman-ford\":3,\"./betweenness-centrality\":4,\"./bfs-dfs\":5,\"./closeness-centrality\":6,\"./degree-centrality\":7,\"./floyd-warshall\":8,\"./kerger-stein\":10,\"./page-rank\":11}],10:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\n\nvar elesfn = ({\n\n  // Computes the minimum cut of an undirected graph\n  // Returns the correct answer with high probability\n  kargerStein: function(options) {\n    var eles = this;\n\n    options = options || {};\n\n    // Function which colapses 2 (meta) nodes into one\n    // Updates the remaining edge lists\n    // Receives as a paramater the edge which causes the collapse\n    var colapse = function(edgeIndex, nodeMap, remainingEdges) {\n      var edgeInfo = remainingEdges[edgeIndex];\n      var sourceIn = edgeInfo[1];\n      var targetIn = edgeInfo[2];\n      var partition1 = nodeMap[sourceIn];\n      var partition2 = nodeMap[targetIn];\n\n      // Delete all edges between partition1 and partition2\n      var newEdges = remainingEdges.filter(function(edge) {\n        if (nodeMap[edge[1]] === partition1 && nodeMap[edge[2]] === partition2) {\n          return false;\n        }\n        if (nodeMap[edge[1]] === partition2 && nodeMap[edge[2]] === partition1) {\n          return false;\n        }\n        return true;\n      });\n\n      // All edges pointing to partition2 should now point to partition1\n      for (var i = 0; i < newEdges.length; i++) {\n        var edge = newEdges[i];\n        if (edge[1] === partition2) { // Check source\n          newEdges[i] = edge.slice(0);\n          newEdges[i][1] = partition1;\n        } else if (edge[2] === partition2) { // Check target\n          newEdges[i] = edge.slice(0);\n          newEdges[i][2] = partition1;\n        }\n      }\n\n      // Move all nodes from partition2 to partition1\n      for (var i = 0; i < nodeMap.length; i++) {\n        if (nodeMap[i] === partition2) {\n          nodeMap[i] = partition1;\n        }\n      }\n\n      return newEdges;\n    };\n\n\n    // Contracts a graph until we reach a certain number of meta nodes\n    var contractUntil = function(metaNodeMap,\n                   remainingEdges,\n                   size,\n                   sizeLimit) {\n      // Stop condition\n      if (size <= sizeLimit) {\n        return remainingEdges;\n      }\n\n      // Choose an edge randomly\n      var edgeIndex = Math.floor((Math.random() * remainingEdges.length));\n\n      // Colapse graph based on edge\n      var newEdges = colapse(edgeIndex, metaNodeMap, remainingEdges);\n\n      return contractUntil(metaNodeMap,\n                 newEdges,\n                 size - 1,\n                 sizeLimit);\n    };\n\n    var cy = this._private.cy;\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n    var numEdges = edges.length;\n    var numIter = Math.ceil(Math.pow(Math.log(numNodes) / Math.LN2, 2));\n    var stopSize = Math.floor(numNodes / Math.sqrt(2));\n\n    if (numNodes < 2) {\n      util.error(\"At least 2 nodes are required for Karger-Stein algorithm\");\n      return undefined;\n    }\n\n    // Create numerical identifiers for each node\n    // mapping: node id -> position in nodes array\n    // for reverse mapping, simply use nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Now store edge destination as indexes\n    // Format for each edge (edge index, source node index, target node index)\n    var edgeIndexes = [];\n    for (var i = 0; i < numEdges; i++) {\n      var e = edges[i];\n      edgeIndexes.push([i, id2position[e.source().id()], id2position[e.target().id()]]);\n    }\n\n    // We will store the best cut found here\n    var minCutSize = Infinity;\n    var minCut;\n\n    // Initial meta node partition\n    var originalMetaNode = [];\n    for (var i = 0; i < numNodes; i++) {\n      originalMetaNode.push(i);\n    }\n\n    // Main loop\n    for (var iter = 0; iter <= numIter; iter++) {\n      // Create new meta node partition\n      var metaNodeMap = originalMetaNode.slice(0);\n\n      // Contract until stop point (stopSize nodes)\n      var edgesState = contractUntil(metaNodeMap, edgeIndexes, numNodes, stopSize);\n\n      // Create a copy of the colapsed nodes state\n      var metaNodeMap2 = metaNodeMap.slice(0);\n\n      // Run 2 iterations starting in the stop state\n      var res1 = contractUntil(metaNodeMap, edgesState, stopSize, 2);\n      var res2 = contractUntil(metaNodeMap2, edgesState, stopSize, 2);\n\n      // Is any of the 2 results the best cut so far?\n      if (res1.length <= res2.length && res1.length < minCutSize) {\n        minCutSize = res1.length;\n        minCut = [res1, metaNodeMap];\n      } else if (res2.length <= res1.length && res2.length < minCutSize) {\n        minCutSize = res2.length;\n        minCut = [res2, metaNodeMap2];\n      }\n    } // end of main loop\n\n\n    // Construct result\n    var resEdges = (minCut[0]).map(function(e){ return edges[e[0]]; });\n    var partition1 = [];\n    var partition2 = [];\n\n    // traverse metaNodeMap for best cut\n    var witnessNodePartition = minCut[1][0];\n    for (var i = 0; i < minCut[1].length; i++) {\n      var partitionId = minCut[1][i];\n      if (partitionId === witnessNodePartition) {\n        partition1.push(nodes[i]);\n      } else {\n        partition2.push(nodes[i]);\n      }\n    }\n\n    var ret = {\n      cut: eles.spawn(cy, resEdges),\n      partition1: eles.spawn(partition1),\n      partition2: eles.spawn(partition2)\n    };\n\n    return ret;\n  }\n}); // elesfn\n\n\nmodule.exports = elesfn;\n\n},{\"../../util\":94}],11:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../is');\n\nvar elesfn = ({\n\n  pageRank: function(options) {\n    options = options || {};\n\n    var normalizeVector = function(vector) {\n      var length = vector.length;\n\n      // First, get sum of all elements\n      var total = 0;\n      for (var i = 0; i < length; i++) {\n        total += vector[i];\n      }\n\n      // Now, divide each by the sum of all elements\n      for (var i = 0; i < length; i++) {\n        vector[i] = vector[i] / total;\n      }\n    };\n\n    // dampingFactor - optional\n    if (options != null &&\n      options.dampingFactor != null) {\n      var dampingFactor = options.dampingFactor;\n    } else {\n      var dampingFactor = 0.8; // Default damping factor\n    }\n\n    // desired precision - optional\n    if (options != null &&\n      options.precision != null) {\n      var epsilon = options.precision;\n    } else {\n      var epsilon = 0.000001; // Default precision\n    }\n\n    // Max number of iterations - optional\n    if (options != null &&\n      options.iterations != null) {\n      var numIter = options.iterations;\n    } else {\n      var numIter = 200; // Default number of iterations\n    }\n\n    // Weight function - optional\n    if (options != null &&\n      options.weight != null &&\n      is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    var cy = this._private.cy;\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n    var numEdges = edges.length;\n\n    // Create numerical identifiers for each node\n    // mapping: node id -> position in nodes array\n    // for reverse mapping, simply use nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Construct transposed adjacency matrix\n    // First lets have a zeroed matrix of the right size\n    // We'll also keep track of the sum of each column\n    var matrix = [];\n    var columnSum = [];\n    var additionalProb = (1 - dampingFactor) / numNodes;\n\n    // Create null matric\n    for (var i = 0; i < numNodes; i++) {\n      var newRow = [];\n      for (var j = 0; j < numNodes; j++) {\n        newRow.push(0.0);\n      }\n      matrix.push(newRow);\n      columnSum.push(0.0);\n    }\n\n    // Now, process edges\n    for (var i = 0; i < numEdges; i++) {\n      var edge = edges[i];\n      var s = id2position[edge.source().id()];\n      var t = id2position[edge.target().id()];\n      var w = weightFn.apply(edge, [edge]);\n\n      // Update matrix\n      matrix[t][s] += w;\n\n      // Update column sum\n      columnSum[s] += w;\n    }\n\n    // Add additional probability based on damping factor\n    // Also, take into account columns that have sum = 0\n    var p = 1.0 / numNodes + additionalProb; // Shorthand\n    // Traverse matrix, column by column\n    for (var j = 0; j < numNodes; j++) {\n      if (columnSum[j] === 0) {\n        // No 'links' out from node jth, assume equal probability for each possible node\n        for (var i = 0; i < numNodes; i++) {\n          matrix[i][j] = p;\n        }\n      } else {\n        // Node jth has outgoing link, compute normalized probabilities\n        for (var i = 0; i < numNodes; i++) {\n          matrix[i][j] = matrix[i][j] / columnSum[j] + additionalProb;\n        }\n      }\n    }\n\n    // Compute dominant eigenvector using power method\n    var eigenvector = [];\n    var nullVector = [];\n    var previous;\n\n    // Start with a vector of all 1's\n    // Also, initialize a null vector which will be used as shorthand\n    for (var i = 0; i < numNodes; i++) {\n      eigenvector.push(1.0);\n      nullVector.push(0.0);\n    }\n\n    for (var iter = 0; iter < numIter; iter++) {\n      // New array with all 0's\n      var temp = nullVector.slice(0);\n\n      // Multiply matrix with previous result\n      for (var i = 0; i < numNodes; i++) {\n        for (var j = 0; j < numNodes; j++) {\n          temp[i] += matrix[i][j] * eigenvector[j];\n        }\n      }\n\n      normalizeVector(temp);\n      previous = eigenvector;\n      eigenvector = temp;\n\n      var diff = 0;\n      // Compute difference (squared module) of both vectors\n      for (var i = 0; i < numNodes; i++) {\n        diff += Math.pow(previous[i] - eigenvector[i], 2);\n      }\n\n      // If difference is less than the desired threshold, stop iterating\n      if (diff < epsilon) {\n        break;\n      }\n    }\n\n    // Construct result\n    var res = {\n      rank : function(node) {\n        if (is.string(node)) {\n          // is a selector string\n          var nodeId = (cy.filter(node)[0]).id();\n        } else {\n          // is a node object\n          var nodeId = node.id();\n        }\n        return eigenvector[id2position[nodeId]];\n      }\n    };\n\n\n    return res;\n  } // pageRank\n\n}); // elesfn\n\nmodule.exports = elesfn;\n\n},{\"../../is\":77}],12:[function(_dereq_,module,exports){\n'use strict';\n\nvar define = _dereq_('../define');\n\nvar elesfn = ({\n  animate: define.animate(),\n  animation: define.animation(),\n  animated: define.animated(),\n  clearQueue: define.clearQueue(),\n  delay: define.delay(),\n  delayAnimation: define.delayAnimation(),\n  stop: define.stop()\n});\n\nmodule.exports = elesfn;\n\n},{\"../define\":41}],13:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\n\nvar elesfn = ({\n  classes: function( classes ){\n    classes = classes.match(/\\S+/g) || [];\n    var self = this;\n    var changed = [];\n    var classesMap = {};\n\n    // fill in classes map\n    for( var i = 0; i < classes.length; i++ ){\n      var cls = classes[i];\n\n      classesMap[ cls ] = true;\n    }\n\n    // check and update each ele\n    for( var j = 0; j < self.length; j++ ){\n      var ele = self[j];\n      var _p = ele._private;\n      var eleClasses = _p.classes;\n      var changedEle = false;\n\n      // check if ele has all of the passed classes\n      for( var i = 0; i < classes.length; i++ ){\n        var cls = classes[i];\n        var eleHasClass = eleClasses[ cls ];\n\n        if( !eleHasClass ){\n          changedEle = true;\n          break;\n        }\n      }\n\n      // check if ele has classes outside of those passed\n      if( !changedEle ){ for( var eleCls in eleClasses ){\n        var eleHasClass = eleClasses[ eleCls ];\n        var specdClass = classesMap[ eleCls ]; // i.e. this class is passed to the function\n\n        if( eleHasClass && !specdClass ){\n          changedEle = true;\n          break;\n        }\n      } }\n\n      if( changedEle ){\n        _p.classes = util.copy( classesMap );\n\n        changed.push( ele );\n      }\n    }\n\n    // trigger update style on those eles that had class changes\n    if( changed.length > 0 ){\n      this.spawn(changed)\n        .updateStyle()\n        .trigger('class')\n      ;\n    }\n\n    return self;\n  },\n\n  addClass: function( classes ){\n    return this.toggleClass( classes, true );\n  },\n\n  hasClass: function( className ){\n    var ele = this[0];\n    return ( ele != null && ele._private.classes[className] ) ? true : false;\n  },\n\n  toggleClass: function( classesStr, toggle ){\n    var classes = classesStr.match(/\\S+/g) || [];\n    var self = this;\n    var changed = []; // eles who had classes changed\n\n    for( var i = 0, il = self.length; i < il; i++ ){\n      var ele = self[i];\n      var changedEle = false;\n\n      for( var j = 0; j < classes.length; j++ ){\n        var cls = classes[j];\n        var eleClasses = ele._private.classes;\n        var hasClass = eleClasses[cls];\n        var shouldAdd = toggle || (toggle === undefined && !hasClass);\n\n        if( shouldAdd ){\n          eleClasses[cls] = true;\n\n          if( !hasClass && !changedEle ){\n            changed.push(ele);\n            changedEle = true;\n          }\n        } else { // then remove\n          eleClasses[cls] = false;\n\n          if( hasClass && !changedEle ){\n            changed.push(ele);\n            changedEle = true;\n          }\n        }\n\n      } // for j classes\n    } // for i eles\n\n    // trigger update style on those eles that had class changes\n    if( changed.length > 0 ){\n      this.spawn(changed)\n        .updateStyle()\n        .trigger('class')\n      ;\n    }\n\n    return self;\n  },\n\n  removeClass: function( classes ){\n    return this.toggleClass( classes, false );\n  },\n\n  flashClass: function( classes, duration ){\n    var self = this;\n\n    if( duration == null ){\n      duration = 250;\n    } else if( duration === 0 ){\n      return self; // nothing to do really\n    }\n\n    self.addClass( classes );\n    setTimeout(function(){\n      self.removeClass( classes );\n    }, duration);\n\n    return self;\n  }\n});\n\nmodule.exports = elesfn;\n\n},{\"../util\":94}],14:[function(_dereq_,module,exports){\n'use strict';\n\nvar elesfn = ({\n  allAre: function( selector ){\n    return this.filter(selector).length === this.length;\n  },\n\n  is: function( selector ){\n    return this.filter(selector).length > 0;\n  },\n\n  some: function( fn, thisArg ){\n    for( var i = 0; i < this.length; i++ ){\n      var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );\n\n      if( ret ){\n        return true;\n      }\n    }\n\n    return false;\n  },\n\n  every: function( fn, thisArg ){\n    for( var i = 0; i < this.length; i++ ){\n      var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );\n\n      if( !ret ){\n        return false;\n      }\n    }\n\n    return true;\n  },\n\n  same: function( collection ){\n    collection = this.cy().collection( collection );\n\n    // cheap extra check\n    if( this.length !== collection.length ){\n      return false;\n    }\n\n    return this.intersect( collection ).length === this.length;\n  },\n\n  anySame: function( collection ){\n    collection = this.cy().collection( collection );\n\n    return this.intersect( collection ).length > 0;\n  },\n\n  allAreNeighbors: function( collection ){\n    collection = this.cy().collection( collection );\n\n    return this.neighborhood().intersect( collection ).length === collection.length;\n  }\n});\n\nelesfn.allAreNeighbours = elesfn.allAreNeighbors;\n\nmodule.exports = elesfn;\n\n},{}],15:[function(_dereq_,module,exports){\n'use strict';\n\nvar elesfn = ({\n  parent: function( selector ){\n    var parents = [];\n    var cy = this._private.cy;\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      var parent = cy.getElementById( ele._private.data.parent );\n\n      if( parent.size() > 0 ){\n        parents.push( parent );\n      }\n    }\n\n    return this.spawn( parents, { unique: true } ).filter( selector );\n  },\n\n  parents: function( selector ){\n    var parents = [];\n\n    var eles = this.parent();\n    while( eles.nonempty() ){\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n        parents.push( ele );\n      }\n\n      eles = eles.parent();\n    }\n\n    return this.spawn( parents, { unique: true } ).filter( selector );\n  },\n\n  commonAncestors: function( selector ){\n    var ancestors;\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      var parents = ele.parents();\n\n      ancestors = ancestors || parents;\n\n      ancestors = ancestors.intersect( parents ); // current list must be common with current ele parents set\n    }\n\n    return ancestors.filter( selector );\n  },\n\n  orphans: function( selector ){\n    return this.stdFilter(function( ele ){\n      return ele.isNode() && ele.parent().empty();\n    }).filter( selector );\n  },\n\n  nonorphans: function( selector ){\n    return this.stdFilter(function( ele ){\n      return ele.isNode() && ele.parent().nonempty();\n    }).filter( selector );\n  },\n\n  children: function( selector ){\n    var children = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      children = children.concat( ele._private.children );\n    }\n\n    return this.spawn( children, { unique: true } ).filter( selector );\n  },\n\n  siblings: function( selector ){\n    return this.parent().children().not( this ).filter( selector );\n  },\n\n  isParent: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.children.length !== 0;\n    }\n  },\n\n  isChild: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.data.parent !== undefined && ele.parent().length !== 0;\n    }\n  },\n\n  descendants: function( selector ){\n    var elements = [];\n\n    function add( eles ){\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        elements.push( ele );\n\n        if( ele.children().nonempty() ){\n          add( ele.children() );\n        }\n      }\n    }\n\n    add( this.children() );\n\n    return this.spawn( elements, { unique: true } ).filter( selector );\n  }\n});\n\n// aliases\nelesfn.ancestors = elesfn.parents;\n\nmodule.exports = elesfn;\n\n},{}],16:[function(_dereq_,module,exports){\n'use strict';\n\nvar define = _dereq_('../define');\nvar fn, elesfn;\n\nfn = elesfn = ({\n\n  data: define.data({\n    field: 'data',\n    bindingEvent: 'data',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'data',\n    settingTriggersEvent: true,\n    triggerFnName: 'trigger',\n    allowGetting: true,\n    immutableKeys: {\n      'id': true,\n      'source': true,\n      'target': true,\n      'parent': true\n    },\n    updateStyle: true\n  }),\n\n  removeData: define.removeData({\n    field: 'data',\n    event: 'data',\n    triggerFnName: 'trigger',\n    triggerEvent: true,\n    immutableKeys: {\n      'id': true,\n      'source': true,\n      'target': true,\n      'parent': true\n    },\n    updateStyle: true\n  }),\n\n  scratch: define.data({\n    field: 'scratch',\n    bindingEvent: 'scratch',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'scratch',\n    settingTriggersEvent: true,\n    triggerFnName: 'trigger',\n    allowGetting: true,\n    updateStyle: true\n  }),\n\n  removeScratch: define.removeData({\n    field: 'scratch',\n    event: 'scratch',\n    triggerFnName: 'trigger',\n    triggerEvent: true,\n    updateStyle: true\n  }),\n\n  rscratch: define.data({\n    field: 'rscratch',\n    allowBinding: false,\n    allowSetting: true,\n    settingTriggersEvent: false,\n    allowGetting: true\n  }),\n\n  removeRscratch: define.removeData({\n    field: 'rscratch',\n    triggerEvent: false\n  }),\n\n  id: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.data.id;\n    }\n  }\n\n});\n\n// aliases\nfn.attr = fn.data;\nfn.removeAttr = fn.removeData;\n\nmodule.exports = elesfn;\n\n},{\"../define\":41}],17:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\n\nvar elesfn = {};\n\nfunction defineDegreeFunction(callback){\n  return function( includeLoops ){\n    var self = this;\n\n    if( includeLoops === undefined ){\n      includeLoops = true;\n    }\n\n    if( self.length === 0 ){ return; }\n\n    if( self.isNode() && !self.removed() ){\n      var degree = 0;\n      var node = self[0];\n      var connectedEdges = node._private.edges;\n\n      for( var i = 0; i < connectedEdges.length; i++ ){\n        var edge = connectedEdges[i];\n\n        if( !includeLoops && edge.isLoop() ){\n          continue;\n        }\n\n        degree += callback( node, edge );\n      }\n\n      return degree;\n    } else {\n      return;\n    }\n  };\n}\n\nutil.extend(elesfn, {\n  degree: defineDegreeFunction(function(node, edge){\n    if( edge.source().same( edge.target() ) ){\n      return 2;\n    } else {\n      return 1;\n    }\n  }),\n\n  indegree: defineDegreeFunction(function(node, edge){\n    if( edge.target().same(node) ){\n      return 1;\n    } else {\n      return 0;\n    }\n  }),\n\n  outdegree: defineDegreeFunction(function(node, edge){\n    if( edge.source().same(node) ){\n      return 1;\n    } else {\n      return 0;\n    }\n  })\n});\n\nfunction defineDegreeBoundsFunction(degreeFn, callback){\n  return function( includeLoops ){\n    var ret;\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){\n      var ele = nodes[i];\n      var degree = ele[degreeFn]( includeLoops );\n      if( degree !== undefined && (ret === undefined || callback(degree, ret)) ){\n        ret = degree;\n      }\n    }\n\n    return ret;\n  };\n}\n\nutil.extend(elesfn, {\n  minDegree: defineDegreeBoundsFunction('degree', function(degree, min){\n    return degree < min;\n  }),\n\n  maxDegree: defineDegreeBoundsFunction('degree', function(degree, max){\n    return degree > max;\n  }),\n\n  minIndegree: defineDegreeBoundsFunction('indegree', function(degree, min){\n    return degree < min;\n  }),\n\n  maxIndegree: defineDegreeBoundsFunction('indegree', function(degree, max){\n    return degree > max;\n  }),\n\n  minOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, min){\n    return degree < min;\n  }),\n\n  maxOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, max){\n    return degree > max;\n  })\n});\n\nutil.extend(elesfn, {\n  totalDegree: function( includeLoops ){\n    var total = 0;\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){\n      total += nodes[i].degree( includeLoops );\n    }\n\n    return total;\n  }\n});\n\nmodule.exports = elesfn;\n\n},{\"../util\":94}],18:[function(_dereq_,module,exports){\n'use strict';\n\nvar define = _dereq_('../define');\nvar is = _dereq_('../is');\nvar util = _dereq_('../util');\nvar fn, elesfn;\n\nfn = elesfn = ({\n\n  position: define.data({\n    field: 'position',\n    bindingEvent: 'position',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'position',\n    settingTriggersEvent: true,\n    triggerFnName: 'rtrigger',\n    allowGetting: true,\n    validKeys: ['x', 'y'],\n    onSet: function( eles ){\n      var updatedEles = eles.updateCompoundBounds();\n      updatedEles.rtrigger('position');\n    },\n    canSet: function( ele ){\n      return !ele.locked() && !ele.isParent();\n    }\n  }),\n\n  // position but no notification to renderer\n  silentPosition: define.data({\n    field: 'position',\n    bindingEvent: 'position',\n    allowBinding: false,\n    allowSetting: true,\n    settingEvent: 'position',\n    settingTriggersEvent: false,\n    triggerFnName: 'trigger',\n    allowGetting: true,\n    validKeys: ['x', 'y'],\n    onSet: function( eles ){\n      eles.updateCompoundBounds();\n    },\n    canSet: function( ele ){\n      return !ele.locked() && !ele.isParent();\n    }\n  }),\n\n  positions: function( pos, silent ){\n    if( is.plainObject(pos) ){\n      this.position(pos);\n\n    } else if( is.fn(pos) ){\n      var fn = pos;\n\n      for( var i = 0; i < this.length; i++ ){\n        var ele = this[i];\n\n        var pos = fn.apply(ele, [i, ele]);\n\n        if( pos && !ele.locked() && !ele.isParent() ){\n          var elePos = ele._private.position;\n          elePos.x = pos.x;\n          elePos.y = pos.y;\n        }\n      }\n\n      var updatedEles = this.updateCompoundBounds();\n      var toTrigger = updatedEles.length > 0 ? this.add( updatedEles ) : this;\n\n      if( silent ){\n        toTrigger.trigger('position');\n      } else {\n        toTrigger.rtrigger('position');\n      }\n    }\n\n    return this; // chaining\n  },\n\n  silentPositions: function( pos ){\n    return this.positions( pos, true );\n  },\n\n  // get/set the rendered (i.e. on screen) positon of the element\n  renderedPosition: function( dim, val ){\n    var ele = this[0];\n    var cy = this.cy();\n    var zoom = cy.zoom();\n    var pan = cy.pan();\n    var rpos = is.plainObject( dim ) ? dim : undefined;\n    var setting = rpos !== undefined || ( val !== undefined && is.string(dim) );\n\n    if( ele && ele.isNode() ){ // must have an element and must be a node to return position\n      if( setting ){\n        for( var i = 0; i < this.length; i++ ){\n          var ele = this[i];\n\n          if( val !== undefined ){ // set one dimension\n            ele._private.position[dim] = ( val - pan[dim] )/zoom;\n          } else if( rpos !== undefined ){ // set whole position\n            ele._private.position = {\n              x: ( rpos.x - pan.x ) /zoom,\n              y: ( rpos.y - pan.y ) /zoom\n            };\n          }\n        }\n\n        this.rtrigger('position');\n      } else { // getting\n        var pos = ele._private.position;\n        rpos = {\n          x: pos.x * zoom + pan.x,\n          y: pos.y * zoom + pan.y\n        };\n\n        if( dim === undefined ){ // then return the whole rendered position\n          return rpos;\n        } else { // then return the specified dimension\n          return rpos[ dim ];\n        }\n      }\n    } else if( !setting ){\n      return undefined; // for empty collection case\n    }\n\n    return this; // chaining\n  },\n\n  // get/set the position relative to the parent\n  relativePosition: function( dim, val ){\n    var ele = this[0];\n    var cy = this.cy();\n    var ppos = is.plainObject( dim ) ? dim : undefined;\n    var setting = ppos !== undefined || ( val !== undefined && is.string(dim) );\n    var hasCompoundNodes = cy.hasCompoundNodes();\n\n    if( ele && ele.isNode() ){ // must have an element and must be a node to return position\n      if( setting ){\n        for( var i = 0; i < this.length; i++ ){\n          var ele = this[i];\n          var parent = hasCompoundNodes ? ele.parent() : null;\n          var hasParent = parent && parent.length > 0;\n          var relativeToParent = hasParent;\n\n          if( hasParent ){\n            parent = parent[0];\n          }\n\n          var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };\n\n          if( val !== undefined ){ // set one dimension\n            ele._private.position[dim] = val + origin[dim];\n          } else if( ppos !== undefined ){ // set whole position\n            ele._private.position = {\n              x: ppos.x + origin.x,\n              y: ppos.y + origin.y\n            };\n          }\n        }\n\n        this.rtrigger('position');\n\n      } else { // getting\n        var pos = ele._private.position;\n        var parent = hasCompoundNodes ? ele.parent() : null;\n        var hasParent = parent && parent.length > 0;\n        var relativeToParent = hasParent;\n\n        if( hasParent ){\n          parent = parent[0];\n        }\n\n        var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };\n\n        ppos = {\n          x: pos.x - origin.x,\n          y: pos.y - origin.y\n        };\n\n        if( dim === undefined ){ // then return the whole rendered position\n          return ppos;\n        } else { // then return the specified dimension\n          return ppos[ dim ];\n        }\n      }\n    } else if( !setting ){\n      return undefined; // for empty collection case\n    }\n\n    return this; // chaining\n  },\n\n  renderedBoundingBox: function( options ){\n    var bb = this.boundingBox( options );\n    var cy = this.cy();\n    var zoom = cy.zoom();\n    var pan = cy.pan();\n\n    var x1 = bb.x1 * zoom + pan.x;\n    var x2 = bb.x2 * zoom + pan.x;\n    var y1 = bb.y1 * zoom + pan.y;\n    var y2 = bb.y2 * zoom + pan.y;\n\n    return {\n      x1: x1,\n      x2: x2,\n      y1: y1,\n      y2: y2,\n      w: x2 - x1,\n      h: y2 - y1\n    };\n  },\n\n  updateCompoundBounds: function(){\n    var cy = this.cy();\n\n    if( !cy.styleEnabled() || !cy.hasCompoundNodes() ){ return cy.collection(); } // save cycles for non compound graphs or when style disabled\n\n    var updated = [];\n\n    function update( parent ){\n      var children = parent.children();\n      var style = parent._private.style;\n      var includeLabels = style['compound-sizing-wrt-labels'].value === 'include';\n      var bb = children.boundingBox({ includeLabels: includeLabels, includeEdges: true });\n      var padding = {\n        top: style['padding-top'].pfValue,\n        bottom: style['padding-bottom'].pfValue,\n        left: style['padding-left'].pfValue,\n        right: style['padding-right'].pfValue\n      };\n      var pos = parent._private.position;\n      var didUpdate = false;\n\n      if( style['width'].value === 'auto' ){\n        parent._private.autoWidth = bb.w;\n        pos.x = (bb.x1 + bb.x2 - padding.left + padding.right)/2;\n        didUpdate = true;\n      }\n\n      if( style['height'].value === 'auto' ){\n        parent._private.autoHeight = bb.h;\n        pos.y = (bb.y1 + bb.y2 - padding.top + padding.bottom)/2;\n        didUpdate = true;\n      }\n\n      if( didUpdate ){\n        updated.push( parent );\n      }\n    }\n\n    // go up, level by level\n    var eles = this.parent();\n    while( eles.nonempty() ){\n\n      // update each parent node in this level\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        update( ele );\n      }\n\n      // next level\n      eles = eles.parent();\n    }\n\n    // return changed\n    return this.spawn( updated );\n  },\n\n  // get the bounding box of the elements (in raw model position)\n  boundingBox: function( options ){\n    var eles = this;\n    var cy = eles._private.cy;\n    var cy_p = cy._private;\n    var styleEnabled = cy_p.styleEnabled;\n\n    options = options || util.staticEmptyObject();\n\n    var includeNodes = options.includeNodes === undefined ? true : options.includeNodes;\n    var includeEdges = options.includeEdges === undefined ? true : options.includeEdges;\n    var includeLabels = options.includeLabels === undefined ? true : options.includeLabels;\n\n    // recalculate projections etc\n    if( styleEnabled ){\n      cy_p.renderer.recalculateRenderedStyle( this );\n    }\n\n    var x1 = Infinity;\n    var x2 = -Infinity;\n    var y1 = Infinity;\n    var y2 = -Infinity;\n\n    // find bounds of elements\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var _p = ele._private;\n      var style = _p.style;\n      var display = styleEnabled ? _p.style['display'].value : 'element';\n      var isNode = _p.group === 'nodes';\n      var ex1, ex2, ey1, ey2, x, y;\n      var includedEle = false;\n\n      if( display === 'none' ){ continue; } // then ele doesn't take up space\n\n      if( isNode && includeNodes ){\n        includedEle = true;\n\n        var pos = _p.position;\n        x = pos.x;\n        y = pos.y;\n        var w = ele.outerWidth();\n        var halfW = w/2;\n        var h = ele.outerHeight();\n        var halfH = h/2;\n\n        // handle node dimensions\n        /////////////////////////\n\n        ex1 = x - halfW;\n        ex2 = x + halfW;\n        ey1 = y - halfH;\n        ey2 = y + halfH;\n\n        x1 = ex1 < x1 ? ex1 : x1;\n        x2 = ex2 > x2 ? ex2 : x2;\n        y1 = ey1 < y1 ? ey1 : y1;\n        y2 = ey2 > y2 ? ey2 : y2;\n\n      } else if( ele.isEdge() && includeEdges ){\n        includedEle = true;\n\n        var n1 = _p.source;\n        var n1_p = n1._private;\n        var n1pos = n1_p.position;\n\n        var n2 = _p.target;\n        var n2_p = n2._private;\n        var n2pos = n2_p.position;\n\n\n        // handle edge dimensions (rough box estimate)\n        //////////////////////////////////////////////\n\n        var rstyle = _p.rstyle || {};\n        var w = 0;\n        var wHalf = 0;\n\n        if( styleEnabled ){\n          w = style['width'].pfValue;\n          wHalf = w/2;\n        }\n\n        ex1 = n1pos.x;\n        ex2 = n2pos.x;\n        ey1 = n1pos.y;\n        ey2 = n2pos.y;\n\n        if( ex1 > ex2 ){\n          var temp = ex1;\n          ex1 = ex2;\n          ex2 = temp;\n        }\n\n        if( ey1 > ey2 ){\n          var temp = ey1;\n          ey1 = ey2;\n          ey2 = temp;\n        }\n\n        // take into account edge width\n        ex1 -= wHalf;\n        ex2 += wHalf;\n        ey1 -= wHalf;\n        ey2 += wHalf;\n\n        x1 = ex1 < x1 ? ex1 : x1;\n        x2 = ex2 > x2 ? ex2 : x2;\n        y1 = ey1 < y1 ? ey1 : y1;\n        y2 = ey2 > y2 ? ey2 : y2;\n\n        // handle points along edge (sanity check)\n        //////////////////////////////////////////\n\n        if( styleEnabled ){\n          var pts = rstyle.bezierPts || rstyle.linePts || [];\n\n          for( var j = 0; j < pts.length; j++ ){\n            var pt = pts[j];\n\n            ex1 = pt.x - wHalf;\n            ex2 = pt.x + wHalf;\n            ey1 = pt.y - wHalf;\n            ey2 = pt.y + wHalf;\n\n            x1 = ex1 < x1 ? ex1 : x1;\n            x2 = ex2 > x2 ? ex2 : x2;\n            y1 = ey1 < y1 ? ey1 : y1;\n            y2 = ey2 > y2 ? ey2 : y2;\n          }\n        }\n\n        // precise haystacks (sanity check)\n        ///////////////////////////////////\n\n        if( styleEnabled && style['curve-style'].strValue === 'haystack' ){\n          var hpts = rstyle.haystackPts;\n\n          ex1 = hpts[0].x;\n          ey1 = hpts[0].y;\n          ex2 = hpts[1].x;\n          ey2 = hpts[1].y;\n\n          if( ex1 > ex2 ){\n            var temp = ex1;\n            ex1 = ex2;\n            ex2 = temp;\n          }\n\n          if( ey1 > ey2 ){\n            var temp = ey1;\n            ey1 = ey2;\n            ey2 = temp;\n          }\n\n          x1 = ex1 < x1 ? ex1 : x1;\n          x2 = ex2 > x2 ? ex2 : x2;\n          y1 = ey1 < y1 ? ey1 : y1;\n          y2 = ey2 > y2 ? ey2 : y2;\n        }\n\n      } // edges\n\n\n      // handle label dimensions\n      //////////////////////////\n\n      if( styleEnabled ){\n\n        var _p = ele._private;\n        var style = _p.style;\n        var rstyle = _p.rstyle;\n        var label = style['label'].strValue;\n        var fontSize = style['font-size'];\n        var halign = style['text-halign'];\n        var valign = style['text-valign'];\n        var labelWidth = rstyle.labelWidth;\n        var labelHeight = rstyle.labelHeight;\n        var labelX = rstyle.labelX;\n        var labelY = rstyle.labelY;\n        var isEdge = ele.isEdge();\n        var autorotate = style['edge-text-rotation'].strValue === 'autorotate';\n\n        if( includeLabels && label && fontSize && labelHeight != null && labelWidth != null && labelX != null && labelY != null && halign && valign ){\n          var lh = labelHeight;\n          var lw = labelWidth;\n          var lx1, lx2, ly1, ly2;\n\n          if( isEdge ){\n            lx1 = labelX - lw/2;\n            lx2 = labelX + lw/2;\n            ly1 = labelY - lh/2;\n            ly2 = labelY + lh/2;\n\n            if( autorotate ){\n              var theta = _p.rscratch.labelAngle;\n              var cos = Math.cos( theta );\n              var sin = Math.sin( theta );\n\n              var rotate = function( x, y ){\n                x = x - labelX;\n                y = y - labelY;\n\n                return {\n                  x: x*cos - y*sin + labelX,\n                  y: x*sin + y*cos + labelY\n                };\n              };\n\n              var px1y1 = rotate( lx1, ly1 );\n              var px1y2 = rotate( lx1, ly2 );\n              var px2y1 = rotate( lx2, ly1 );\n              var px2y2 = rotate( lx2, ly2 );\n\n              lx1 = Math.min( px1y1.x, px1y2.x, px2y1.x, px2y2.x );\n              lx2 = Math.max( px1y1.x, px1y2.x, px2y1.x, px2y2.x );\n              ly1 = Math.min( px1y1.y, px1y2.y, px2y1.y, px2y2.y );\n              ly2 = Math.max( px1y1.y, px1y2.y, px2y1.y, px2y2.y );\n            }\n          } else {\n            switch( halign.value ){\n              case 'left':\n                lx1 = labelX - lw;\n                lx2 = labelX;\n                break;\n\n              case 'center':\n                lx1 = labelX - lw/2;\n                lx2 = labelX + lw/2;\n                break;\n\n              case 'right':\n                lx1 = labelX;\n                lx2 = labelX + lw;\n                break;\n            }\n\n            switch( valign.value ){\n              case 'top':\n                ly1 = labelY - lh;\n                ly2 = labelY;\n                break;\n\n              case 'center':\n                ly1 = labelY - lh/2;\n                ly2 = labelY + lh/2;\n                break;\n\n              case 'bottom':\n                ly1 = labelY;\n                ly2 = labelY + lh;\n                break;\n            }\n          }\n\n          x1 = lx1 < x1 ? lx1 : x1;\n          x2 = lx2 > x2 ? lx2 : x2;\n          y1 = ly1 < y1 ? ly1 : y1;\n          y2 = ly2 > y2 ? ly2 : y2;\n        }\n      } // style enabled for labels\n    } // for\n\n    var noninf = function(x){\n      if( x === Infinity || x === -Infinity ){\n        return 0;\n      }\n\n      return x;\n    };\n\n    x1 = noninf(x1);\n    x2 = noninf(x2);\n    y1 = noninf(y1);\n    y2 = noninf(y2);\n\n    return {\n      x1: x1,\n      x2: x2,\n      y1: y1,\n      y2: y2,\n      w: x2 - x1,\n      h: y2 - y1\n    };\n  }\n});\n\nvar defineDimFns = function( opts ){\n  opts.uppercaseName = util.capitalize( opts.name );\n  opts.autoName = 'auto' + opts.uppercaseName;\n  opts.labelName = 'label' + opts.uppercaseName;\n  opts.outerName = 'outer' + opts.uppercaseName;\n  opts.uppercaseOuterName = util.capitalize( opts.outerName );\n\n  fn[ opts.name ] = function dimImpl(){\n    var ele = this[0];\n    var _p = ele._private;\n    var cy = _p.cy;\n    var styleEnabled = cy._private.styleEnabled;\n\n    if( ele ){\n      if( styleEnabled ){\n        var d = _p.style[ opts.name ];\n\n        switch( d.strValue ){\n          case 'auto':\n            return _p[ opts.autoName ] || 0;\n          case 'label':\n            return _p.rstyle[ opts.labelName ] || 0;\n          default:\n            return d.pfValue;\n        }\n      } else {\n        return 1;\n      }\n    }\n  };\n\n  fn[ 'outer' + opts.uppercaseName ] = function outerDimImpl(){\n    var ele = this[0];\n    var _p = ele._private;\n    var cy = _p.cy;\n    var styleEnabled = cy._private.styleEnabled;\n\n    if( ele ){\n      if( styleEnabled ){\n        var style = _p.style;\n        var dim = ele[ opts.name ]();\n        var border = style['border-width'].pfValue;\n        var padding = style[ opts.paddings[0] ].pfValue + style[ opts.paddings[1] ].pfValue;\n\n        return dim + border + padding;\n      } else {\n        return 1;\n      }\n    }\n  };\n\n  fn[ 'rendered' + opts.uppercaseName ] = function renderedDimImpl(){\n    var ele = this[0];\n\n    if( ele ){\n      var d = ele[ opts.name ]();\n      return d * this.cy().zoom();\n    }\n  };\n\n  fn[ 'rendered' + opts.uppercaseOuterName ] = function renderedOuterDimImpl(){\n    var ele = this[0];\n\n    if( ele ){\n      var od = ele[ opts.outerName ]();\n      return od * this.cy().zoom();\n    }\n  };\n};\n\ndefineDimFns({\n  name: 'width',\n  paddings: ['padding-left', 'padding-right']\n});\n\ndefineDimFns({\n  name: 'height',\n  paddings: ['padding-top', 'padding-bottom']\n});\n\n// aliases\nfn.modelPosition = fn.point = fn.position;\nfn.modelPositions = fn.points = fn.positions;\nfn.renderedPoint = fn.renderedPosition;\nfn.relativePoint = fn.relativePosition;\nfn.boundingbox = fn.boundingBox;\nfn.renderedBoundingbox = fn.renderedBoundingBox;\n\nmodule.exports = elesfn;\n\n},{\"../define\":41,\"../is\":77,\"../util\":94}],19:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\n// represents a node or an edge\nvar Element = function(cy, params, restore){\n  if( !(this instanceof Element) ){\n    return new Element(cy, params, restore);\n  }\n\n  var self = this;\n  restore = (restore === undefined || restore ? true : false);\n\n  if( cy === undefined || params === undefined || !is.core(cy) ){\n    util.error('An element must have a core reference and parameters set');\n    return;\n  }\n\n  var group = params.group;\n\n  // try to automatically infer the group if unspecified\n  if( group == null ){\n    if( params.data.source != null && params.data.target != null ){\n      group = 'edges';\n    } else {\n      group = 'nodes';\n    }\n  }\n\n  // validate group\n  if( group !== 'nodes' && group !== 'edges' ){\n    util.error('An element must be of type `nodes` or `edges`; you specified `' + group + '`');\n    return;\n  }\n\n  // make the element array-like, just like a collection\n  this.length = 1;\n  this[0] = this;\n\n  // NOTE: when something is added here, add also to ele.json()\n  this._private = {\n    cy: cy,\n    single: true, // indicates this is an element\n    data: params.data || {}, // data object\n    position: params.position || {}, // (x, y) position pair\n    autoWidth: undefined, // width and height of nodes calculated by the renderer when set to special 'auto' value\n    autoHeight: undefined,\n    listeners: [], // array of bound listeners\n    group: group, // string; 'nodes' or 'edges'\n    style: {}, // properties as set by the style\n    rstyle: {}, // properties for style sent from the renderer to the core\n    styleCxts: [], // applied style contexts from the styler\n    removed: true, // whether it's inside the vis; true if removed (set true here since we call restore)\n    selected: params.selected ? true : false, // whether it's selected\n    selectable: params.selectable === undefined ? true : ( params.selectable ? true : false ), // whether it's selectable\n    locked: params.locked ? true : false, // whether the element is locked (cannot be moved)\n    grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately\n    grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), // whether the element can be grabbed\n    active: false, // whether the element is active from user interaction\n    classes: {}, // map ( className => true )\n    animation: { // object for currently-running animations\n      current: [],\n      queue: []\n    },\n    rscratch: {}, // object in which the renderer can store information\n    scratch: params.scratch || {}, // scratch objects\n    edges: [], // array of connected edges\n    children: [] // array of children\n  };\n\n  // renderedPosition overrides if specified\n  if( params.renderedPosition ){\n    var rpos = params.renderedPosition;\n    var pan = cy.pan();\n    var zoom = cy.zoom();\n\n    this._private.position = {\n      x: (rpos.x - pan.x)/zoom,\n      y: (rpos.y - pan.y)/zoom\n    };\n  }\n\n  if( is.string(params.classes) ){\n    var classes = params.classes.split(/\\s+/);\n    for( var i = 0, l = classes.length; i < l; i++ ){\n      var cls = classes[i];\n      if( !cls || cls === '' ){ continue; }\n\n      self._private.classes[cls] = true;\n    }\n  }\n\n  if( params.style || params.css ){\n    cy.style().applyBypass( this, params.style || params.css );\n  }\n\n  if( restore === undefined || restore ){\n    this.restore();\n  }\n\n};\n\nmodule.exports = Element;\n\n},{\"../is\":77,\"../util\":94}],20:[function(_dereq_,module,exports){\n'use strict';\n\nvar define = _dereq_('../define');\n\nvar elesfn = ({\n  on: define.on(), // .on( events [, selector] [, data], handler)\n  one: define.on({ unbindSelfOnTrigger: true }),\n  once: define.on({ unbindAllBindersOnTrigger: true }),\n  off: define.off(), // .off( events [, selector] [, handler] )\n  trigger: define.trigger(), // .trigger( events [, extraParams] )\n\n  rtrigger: function(event, extraParams){ // for internal use only\n    if( this.length === 0 ){ return; } // empty collections don't need to notify anything\n\n    // notify renderer\n    this.cy().notify({\n      type: event,\n      collection: this\n    });\n\n    this.trigger(event, extraParams);\n    return this;\n  }\n});\n\n// aliases:\ndefine.eventAliasesOn( elesfn );\n\nmodule.exports = elesfn;\n\n},{\"../define\":41}],21:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar Selector = _dereq_('../selector');\n\nvar elesfn = ({\n  nodes: function( selector ){\n    return this.filter(function(i, element){\n      return element.isNode();\n    }).filter(selector);\n  },\n\n  edges: function( selector ){\n    return this.filter(function(i, element){\n      return element.isEdge();\n    }).filter(selector);\n  },\n\n  filter: function( filter ){\n    if( is.fn(filter) ){\n      var elements = [];\n\n      for( var i = 0; i < this.length; i++ ){\n        var ele = this[i];\n\n        if( filter.apply(ele, [i, ele]) ){\n          elements.push(ele);\n        }\n      }\n\n      return this.spawn(elements);\n\n    } else if( is.string(filter) || is.elementOrCollection(filter) ){\n      return Selector(filter).filter(this);\n\n    } else if( filter === undefined ){\n      return this;\n    }\n\n    return this.spawn(); // if not handled by above, give 'em an empty collection\n  },\n\n  not: function( toRemove ){\n    if( !toRemove ){\n      return this;\n    } else {\n\n      if( is.string( toRemove ) ){\n        toRemove = this.filter( toRemove );\n      }\n\n      var elements = [];\n\n      for( var i = 0; i < this.length; i++ ){\n        var element = this[i];\n\n        var remove = toRemove._private.ids[ element.id() ];\n        if( !remove ){\n          elements.push( element );\n        }\n      }\n\n      return this.spawn( elements );\n    }\n\n  },\n\n  absoluteComplement: function(){\n    var cy = this._private.cy;\n\n    return cy.elements().not( this );\n  },\n\n  intersect: function( other ){\n    // if a selector is specified, then filter by it instead\n    if( is.string(other) ){\n      var selector = other;\n      return this.filter( selector );\n    }\n\n    var elements = [];\n    var col1 = this;\n    var col2 = other;\n    var col1Smaller = this.length < other.length;\n    // var ids1 = col1Smaller ? col1._private.ids : col2._private.ids;\n    var ids2 = col1Smaller ? col2._private.ids : col1._private.ids;\n    var col = col1Smaller ? col1 : col2;\n\n    for( var i = 0; i < col.length; i++ ){\n      var id = col[i]._private.data.id;\n      var ele = ids2[ id ];\n\n      if( ele ){\n        elements.push( ele );\n      }\n    }\n\n    return this.spawn( elements );\n  },\n\n  xor: function( other ){\n    var cy = this._private.cy;\n\n    if( is.string(other) ){\n      other = cy.$( other );\n    }\n\n    var elements = [];\n    var col1 = this;\n    var col2 = other;\n\n    var add = function( col, other ){\n\n      for( var i = 0; i < col.length; i++ ){\n        var ele = col[i];\n        var id = ele._private.data.id;\n        var inOther = other._private.ids[ id ];\n\n        if( !inOther ){\n          elements.push( ele );\n        }\n      }\n\n    };\n\n    add( col1, col2 );\n    add( col2, col1 );\n\n    return this.spawn( elements );\n  },\n\n  diff: function( other ){\n    var cy = this._private.cy;\n\n    if( is.string(other) ){\n      other = cy.$( other );\n    }\n\n    var left = [];\n    var right = [];\n    var both = [];\n    var col1 = this;\n    var col2 = other;\n\n    var add = function( col, other, retEles ){\n\n      for( var i = 0; i < col.length; i++ ){\n        var ele = col[i];\n        var id = ele._private.data.id;\n        var inOther = other._private.ids[ id ];\n\n        if( inOther ){\n          both.push( ele );\n        } else {\n          retEles.push( ele );\n        }\n      }\n\n    };\n\n    add( col1, col2, left );\n    add( col2, col1, right );\n\n    return {\n      left: this.spawn( left, { unique: true } ),\n      right: this.spawn( right, { unique: true } ),\n      both: this.spawn( both, { unique: true } )\n    };\n  },\n\n  add: function( toAdd ){\n    var cy = this._private.cy;\n\n    if( !toAdd ){\n      return this;\n    }\n\n    if( is.string(toAdd) ){\n      var selector = toAdd;\n      toAdd = cy.elements(selector);\n    }\n\n    var elements = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      elements.push( this[i] );\n    }\n\n    for( var i = 0; i < toAdd.length; i++ ){\n\n      var add = !this._private.ids[ toAdd[i].id() ];\n      if( add ){\n        elements.push( toAdd[i] );\n      }\n    }\n\n    return this.spawn(elements);\n  },\n\n  // in place merge on calling collection\n  merge: function( toAdd ){\n    var _p = this._private;\n    var cy = _p.cy;\n\n    if( !toAdd ){\n      return this;\n    }\n\n    if( is.string(toAdd) ){\n      var selector = toAdd;\n      toAdd = cy.elements(selector);\n    }\n\n    for( var i = 0; i < toAdd.length; i++ ){\n      var toAddEle = toAdd[i];\n      var id = toAddEle.id();\n      var add = !_p.ids[ id ];\n\n      if( add ){\n        var index = this.length++;\n\n        this[ index ] = toAddEle;\n        _p.ids[ id ] = toAddEle;\n        _p.indexes[ id ] = index;\n      }\n    }\n\n    return this; // chaining\n  },\n\n  // remove single ele in place in calling collection\n  unmergeOne: function( ele ){\n    ele = ele[0];\n\n    var _p = this._private;\n    var id = ele.id();\n    var i = _p.indexes[ id ];\n\n    if( i == null ){\n      return this; // no need to remove\n    }\n\n    // remove ele\n    this[i] = undefined;\n    _p.ids[ id ] = undefined;\n    _p.indexes[ id ] = undefined;\n\n    var unmergedLastEle = i === this.length - 1;\n\n    // replace empty spot with last ele in collection\n    if( this.length > 1 && !unmergedLastEle ){\n      var lastEleI = this.length - 1;\n      var lastEle = this[ lastEleI ];\n\n      this[ lastEleI ] = undefined;\n      this[i] = lastEle;\n      _p.indexes[ lastEle.id() ] = i;\n    }\n\n    // the collection is now 1 ele smaller\n    this.length--;\n\n    return this;\n  },\n\n  // remove eles in place on calling collection\n  unmerge: function( toRemove ){\n    var cy = this._private.cy;\n\n    if( !toRemove ){\n      return this;\n    }\n\n    if( is.string(toRemove) ){\n      var selector = toRemove;\n      toRemove = cy.elements(selector);\n    }\n\n    for( var i = 0; i < toRemove.length; i++ ){\n      this.unmergeOne( toRemove[i] );\n    }\n\n    return this; // chaining\n  },\n\n  map: function( mapFn, thisArg ){\n    var arr = [];\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var ret = thisArg ? mapFn.apply( thisArg, [ele, i, eles] ) : mapFn( ele, i, eles );\n\n      arr.push( ret );\n    }\n\n    return arr;\n  },\n\n  stdFilter: function( fn, thisArg ){\n    var filterEles = [];\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var include = thisArg ? fn.apply( thisArg, [ele, i, eles] ) : fn( ele, i, eles );\n\n      if( include ){\n        filterEles.push( ele );\n      }\n    }\n\n    return this.spawn( filterEles );\n  },\n\n  max: function( valFn, thisArg ){\n    var max = -Infinity;\n    var maxEle;\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );\n\n      if( val > max ){\n        max = val;\n        maxEle = ele;\n      }\n    }\n\n    return {\n      value: max,\n      ele: maxEle\n    };\n  },\n\n  min: function( valFn, thisArg ){\n    var min = Infinity;\n    var minEle;\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );\n\n      if( val < min ){\n        min = val;\n        minEle = ele;\n      }\n    }\n\n    return {\n      value: min,\n      ele: minEle\n    };\n  }\n});\n\n// aliases\nvar fn = elesfn;\nfn['u'] = fn['|'] = fn['+'] = fn.union = fn.or = fn.add;\nfn['\\\\'] = fn['!'] = fn['-'] = fn.difference = fn.relativeComplement = fn.subtract = fn.not;\nfn['n'] = fn['&'] = fn['.'] = fn.and = fn.intersection = fn.intersect;\nfn['^'] = fn['(+)'] = fn['(-)'] = fn.symmetricDifference = fn.symdiff = fn.xor;\nfn.fnFilter = fn.filterFn = fn.stdFilter;\nfn.complement = fn.abscomp = fn.absoluteComplement;\n\nmodule.exports = elesfn;\n\n},{\"../is\":77,\"../selector\":81}],22:[function(_dereq_,module,exports){\n'use strict';\n\nvar elesfn = ({\n  isNode: function(){\n    return this.group() === 'nodes';\n  },\n\n  isEdge: function(){\n    return this.group() === 'edges';\n  },\n\n  isLoop: function(){\n    return this.isEdge() && this.source().id() === this.target().id();\n  },\n\n  isSimple: function(){\n    return this.isEdge() && this.source().id() !== this.target().id();\n  },\n\n  group: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.group;\n    }\n  }\n});\n\n\nmodule.exports = elesfn;\n\n},{}],23:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\nvar Element = _dereq_('./element');\n\n// factory for generating edge ids when no id is specified for a new element\nvar idFactory = {\n  prefix: 'ele',\n  id: 0,\n  generate: function(cy, element, tryThisId){\n    var json = is.element( element ) ? element._private : element;\n    var id = tryThisId != null ? tryThisId : this.prefix + this.id;\n\n    if( cy.getElementById(id).empty() ){\n      this.id++; // we've used the current id, so move it up\n    } else { // otherwise keep trying successive unused ids\n      while( !cy.getElementById(id).empty() ){\n        id = this.prefix + ( ++this.id );\n      }\n    }\n\n    return id;\n  }\n};\n\n// represents a set of nodes, edges, or both together\nvar Collection = function(cy, elements, options){\n  if( !(this instanceof Collection) ){\n    return new Collection(cy, elements, options);\n  }\n\n  if( cy === undefined || !is.core(cy) ){\n    util.error('A collection must have a reference to the core');\n    return;\n  }\n\n  var ids = {};\n  var indexes = {};\n  var createdElements = false;\n\n  if( !elements ){\n    elements = [];\n  } else if( elements.length > 0 && is.plainObject( elements[0] ) && !is.element( elements[0] ) ){\n    createdElements = true;\n\n    // make elements from json and restore all at once later\n    var eles = [];\n    var elesIds = {};\n\n    for( var i = 0, l = elements.length; i < l; i++ ){\n      var json = elements[i];\n\n      if( json.data == null ){\n        json.data = {};\n      }\n\n      var data = json.data;\n\n      // make sure newly created elements have valid ids\n      if( data.id == null ){\n        data.id = idFactory.generate( cy, json );\n      } else if( cy.getElementById( data.id ).length !== 0 || elesIds[ data.id ] ){\n        continue; // can't create element if prior id already exists\n      }\n\n      var ele = new Element( cy, json, false );\n      eles.push( ele );\n      elesIds[ data.id ] = true;\n    }\n\n    elements = eles;\n  }\n\n  this.length = 0;\n\n  for( var i = 0, l = elements.length; i < l; i++ ){\n    var element = elements[i];\n    if( !element ){  continue; }\n\n    var id = element._private.data.id;\n\n    if( !options || (options.unique && !ids[ id ] ) ){\n      ids[ id ] = element;\n      indexes[ id ] = this.length;\n\n      this[ this.length ] = element;\n      this.length++;\n    }\n  }\n\n  this._private = {\n    cy: cy,\n    ids: ids,\n    indexes: indexes\n  };\n\n  // restore the elements if we created them from json\n  if( createdElements ){\n    this.restore();\n  }\n};\n\n// Functions\n////////////////////////////////////////////////////////////////////////////////////////////////////\n\n// keep the prototypes in sync (an element has the same functions as a collection)\n// and use elefn and elesfn as shorthands to the prototypes\nvar elesfn = Element.prototype = Collection.prototype;\n\nelesfn.instanceString = function(){\n  return 'collection';\n};\n\nelesfn.spawn = function( cy, eles, opts ){\n  if( !is.core(cy) ){ // cy is optional\n    opts = eles;\n    eles = cy;\n    cy = this.cy();\n  }\n\n  return new Collection( cy, eles, opts );\n};\n\nelesfn.cy = function(){\n  return this._private.cy;\n};\n\nelesfn.element = function(){\n  return this[0];\n};\n\nelesfn.collection = function(){\n  if( is.collection(this) ){\n    return this;\n  } else { // an element\n    return new Collection( this._private.cy, [this] );\n  }\n};\n\nelesfn.unique = function(){\n  return new Collection( this._private.cy, this, { unique: true } );\n};\n\nelesfn.getElementById = function( id ){\n  var cy = this._private.cy;\n  var ele = this._private.ids[ id ];\n\n  return ele ? ele : new Collection(cy); // get ele or empty collection\n};\n\nelesfn.json = function( obj ){\n  var ele = this.element();\n  var cy = this.cy();\n\n  if( ele == null && obj ){ return this; } // can't set to no eles\n\n  if( ele == null ){ return undefined; } // can't get from no eles\n\n  var p = ele._private;\n\n  if( is.plainObject(obj) ){ // set\n\n    cy.startBatch();\n\n    if( obj.data ){\n      ele.data( obj.data );\n    }\n\n    if( obj.position ){\n      ele.position( obj.position );\n    }\n\n    // ignore group -- immutable\n\n    var checkSwitch = function( k, trueFnName, falseFnName ){\n      var obj_k = obj[k];\n\n      if( obj_k != null && obj_k !== p[k] ){\n        if( obj_k ){\n          ele[ trueFnName ]();\n        } else {\n          ele[ falseFnName ]();\n        }\n      }\n    };\n\n    checkSwitch( 'removed', 'remove', 'restore' );\n\n    checkSwitch( 'selected', 'select', 'unselect' );\n\n    checkSwitch( 'selectable', 'selectify', 'unselectify' );\n\n    checkSwitch( 'locked', 'lock', 'unlock' );\n\n    checkSwitch( 'grabbable', 'grabify', 'ungrabify' );\n\n    if( obj.classes != null ){\n      ele.classes( obj.classes );\n    }\n\n    cy.endBatch();\n\n    return this;\n\n  } else if( obj === undefined ){ // get\n\n    var json = {\n      data: util.copy( p.data ),\n      position: util.copy( p.position ),\n      group: p.group,\n      removed: p.removed,\n      selected: p.selected,\n      selectable: p.selectable,\n      locked: p.locked,\n      grabbable: p.grabbable,\n      classes: null\n    };\n\n    var classes = [];\n    for( var cls in p.classes ){\n      if( p.classes[cls] ){\n        classes.push(cls);\n      }\n    }\n    json.classes = classes.join(' ');\n\n    return json;\n  }\n};\n\nelesfn.jsons = function(){\n  var jsons = [];\n\n  for( var i = 0; i < this.length; i++ ){\n    var ele = this[i];\n    var json = ele.json();\n\n    jsons.push( json );\n  }\n\n  return jsons;\n};\n\nelesfn.clone = function(){\n  var cy = this.cy();\n  var elesArr = [];\n\n  for( var i = 0; i < this.length; i++ ){\n    var ele = this[i];\n    var json = ele.json();\n    var clone = new Element(cy, json, false); // NB no restore\n\n    elesArr.push( clone );\n  }\n\n  return new Collection( cy, elesArr );\n};\nelesfn.copy = elesfn.clone;\n\nelesfn.restore = function( notifyRenderer ){\n  var self = this;\n  var restored = [];\n  var cy = self.cy();\n\n  if( notifyRenderer === undefined ){\n    notifyRenderer = true;\n  }\n\n  // create arrays of nodes and edges, since we need to\n  // restore the nodes first\n  var elements = [];\n  var nodes = [], edges = [];\n  var numNodes = 0;\n  var numEdges = 0;\n  for( var i = 0, l = self.length; i < l; i++ ){\n    var ele = self[i];\n\n    // keep nodes first in the array and edges after\n    if( ele.isNode() ){ // put to front of array if node\n      nodes.push( ele );\n      numNodes++;\n    } else { // put to end of array if edge\n      edges.push( ele );\n      numEdges++;\n    }\n  }\n\n  elements = nodes.concat( edges );\n\n  // now, restore each element\n  for( var i = 0, l = elements.length; i < l; i++ ){\n    var ele = elements[i];\n\n    if( !ele.removed() ){\n      // don't need to do anything\n      continue;\n    }\n\n    var _private = ele._private;\n    var data = _private.data;\n\n    // set id and validate\n    if( data.id === undefined ){\n      data.id = idFactory.generate( cy, ele );\n\n    } else if( is.number(data.id) ){\n      data.id = '' + data.id; // now it's a string\n\n    } else if( is.emptyString(data.id) || !is.string(data.id) ){\n      util.error('Can not create element with invalid string ID `' + data.id + '`');\n\n      // can't create element if it has empty string as id or non-string id\n      continue;\n    } else if( cy.getElementById( data.id ).length !== 0 ){\n      util.error('Can not create second element with ID `' + data.id + '`');\n\n      // can't create element if one already has that id\n      continue;\n    }\n\n    var id = data.id; // id is finalised, now let's keep a ref\n\n    if( ele.isNode() ){ // extra checks for nodes\n      var node = ele;\n      var pos = _private.position;\n\n      // make sure the nodes have a defined position\n\n      if( pos.x == null ){\n        pos.x = 0;\n      }\n\n      if( pos.y == null ){\n        pos.y = 0;\n      }\n    }\n\n    if( ele.isEdge() ){ // extra checks for edges\n\n      var edge = ele;\n      var fields = ['source', 'target'];\n      var fieldsLength = fields.length;\n      var badSourceOrTarget = false;\n      for(var j = 0; j < fieldsLength; j++){\n\n        var field = fields[j];\n        var val = data[field];\n\n        if( is.number(val) ){\n          val = data[field] = '' + data[field]; // now string\n        }\n\n        if( val == null || val === '' ){\n          // can't create if source or target is not defined properly\n          util.error('Can not create edge `' + id + '` with unspecified ' + field);\n          badSourceOrTarget = true;\n        } else if( cy.getElementById(val).empty() ){\n          // can't create edge if one of its nodes doesn't exist\n          util.error('Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`');\n          badSourceOrTarget = true;\n        }\n      }\n\n      if( badSourceOrTarget ){ continue; } // can't create this\n\n      var src = cy.getElementById( data.source );\n      var tgt = cy.getElementById( data.target );\n\n      src._private.edges.push( edge );\n      tgt._private.edges.push( edge );\n\n      edge._private.source = src;\n      edge._private.target = tgt;\n\n    } // if is edge\n\n    // create mock ids map for element so it can be used like collections\n    _private.ids = {};\n    _private.ids[ id ] = ele;\n\n    _private.removed = false;\n    cy.addToPool( ele );\n\n    restored.push( ele );\n  } // for each element\n\n  // do compound node sanity checks\n  for( var i = 0; i < numNodes; i++ ){ // each node\n    var node = elements[i];\n    var data = node._private.data;\n\n    if( is.number(data.parent) ){ // then automake string\n      data.parent = '' + data.parent;\n    }\n\n    var parentId = data.parent;\n\n    var specifiedParent = parentId != null;\n\n    if( specifiedParent ){\n      var parent = cy.getElementById( parentId );\n\n      if( parent.empty() ){\n        // non-existant parent; just remove it\n        data.parent = undefined;\n      } else {\n        var selfAsParent = false;\n        var ancestor = parent;\n        while( !ancestor.empty() ){\n          if( node.same(ancestor) ){\n            // mark self as parent and remove from data\n            selfAsParent = true;\n            data.parent = undefined; // remove parent reference\n\n            // exit or we loop forever\n            break;\n          }\n\n          ancestor = ancestor.parent();\n        }\n\n        if( !selfAsParent ){\n          // connect with children\n          parent[0]._private.children.push( node );\n          node._private.parent = parent[0];\n\n          // let the core know we have a compound graph\n          cy._private.hasCompoundNodes = true;\n        }\n      } // else\n    } // if specified parent\n  } // for each node\n\n  restored = new Collection( cy, restored );\n  if( restored.length > 0 ){\n\n    var toUpdateStyle = restored.add( restored.connectedNodes() ).add( restored.parent() );\n    toUpdateStyle.updateStyle( notifyRenderer );\n\n    if( notifyRenderer ){\n      restored.rtrigger('add');\n    } else {\n      restored.trigger('add');\n    }\n  }\n\n  return self; // chainability\n};\n\nelesfn.removed = function(){\n  var ele = this[0];\n  return ele && ele._private.removed;\n};\n\nelesfn.inside = function(){\n  var ele = this[0];\n  return ele && !ele._private.removed;\n};\n\nelesfn.remove = function( notifyRenderer ){\n  var self = this;\n  var removed = [];\n  var elesToRemove = [];\n  var elesToRemoveIds = {};\n  var cy = self._private.cy;\n\n  if( notifyRenderer === undefined ){\n    notifyRenderer = true;\n  }\n\n  // add connected edges\n  function addConnectedEdges(node){\n    var edges = node._private.edges;\n    for( var i = 0; i < edges.length; i++ ){\n      add( edges[i] );\n    }\n  }\n\n\n  // add descendant nodes\n  function addChildren(node){\n    var children = node._private.children;\n\n    for( var i = 0; i < children.length; i++ ){\n      add( children[i] );\n    }\n  }\n\n  function add( ele ){\n    var alreadyAdded =  elesToRemoveIds[ ele.id() ];\n    if( alreadyAdded ){\n      return;\n    } else {\n      elesToRemoveIds[ ele.id() ] = true;\n    }\n\n    if( ele.isNode() ){\n      elesToRemove.push( ele ); // nodes are removed last\n\n      addConnectedEdges( ele );\n      addChildren( ele );\n    } else {\n      elesToRemove.unshift( ele ); // edges are removed first\n    }\n  }\n\n  // make the list of elements to remove\n  // (may be removing more than specified due to connected edges etc)\n\n  for( var i = 0, l = self.length; i < l; i++ ){\n    var ele = self[i];\n\n    add( ele );\n  }\n\n  function removeEdgeRef(node, edge){\n    var connectedEdges = node._private.edges;\n    for( var j = 0; j < connectedEdges.length; j++ ){\n      var connectedEdge = connectedEdges[j];\n\n      if( edge === connectedEdge ){\n        connectedEdges.splice( j, 1 );\n        break;\n      }\n    }\n  }\n\n  function removeChildRef(parent, ele){\n    ele = ele[0];\n    parent = parent[0];\n    var children = parent._private.children;\n\n    for( var j = 0; j < children.length; j++ ){\n      if( children[j][0] === ele[0] ){\n        children.splice(j, 1);\n        break;\n      }\n    }\n  }\n\n  for( var i = 0; i < elesToRemove.length; i++ ){\n    var ele = elesToRemove[i];\n\n    // mark as removed\n    ele._private.removed = true;\n\n    // remove from core pool\n    cy.removeFromPool( ele );\n\n    // add to list of removed elements\n    removed.push( ele );\n\n    if( ele.isEdge() ){ // remove references to this edge in its connected nodes\n      var src = ele.source()[0];\n      var tgt = ele.target()[0];\n\n      removeEdgeRef( src, ele );\n      removeEdgeRef( tgt, ele );\n\n    } else { // remove reference to parent\n      var parent = ele.parent();\n\n      if( parent.length !== 0 ){\n        removeChildRef(parent, ele);\n      }\n    }\n  }\n\n  // check to see if we have a compound graph or not\n  var elesStillInside = cy._private.elements;\n  cy._private.hasCompoundNodes = false;\n  for( var i = 0; i < elesStillInside.length; i++ ){\n    var ele = elesStillInside[i];\n\n    if( ele.isParent() ){\n      cy._private.hasCompoundNodes = true;\n      break;\n    }\n  }\n\n  var removedElements = new Collection( this.cy(), removed );\n  if( removedElements.size() > 0 ){\n    // must manually notify since trigger won't do this automatically once removed\n\n    if( notifyRenderer ){\n      this.cy().notify({\n        type: 'remove',\n        collection: removedElements\n      });\n    }\n\n    removedElements.trigger('remove');\n  }\n\n  // check for empty remaining parent nodes\n  var checkedParentId = {};\n  for( var i = 0; i < elesToRemove.length; i++ ){\n    var ele = elesToRemove[i];\n    var isNode = ele._private.group === 'nodes';\n    var parentId = ele._private.data.parent;\n\n    if( isNode && parentId !== undefined && !checkedParentId[ parentId ] ){\n      checkedParentId[ parentId ] = true;\n      var parent = cy.getElementById( parentId );\n\n      if( parent && parent.length !== 0 && !parent._private.removed && parent.children().length === 0 ){\n        parent.updateStyle();\n      }\n    }\n  }\n\n  return new Collection( cy, removed );\n};\n\nelesfn.move = function( struct ){\n  var cy = this._private.cy;\n\n  if( struct.source !== undefined || struct.target !== undefined ){\n    var srcId = struct.source;\n    var tgtId = struct.target;\n    var srcExists = cy.getElementById( srcId ).length > 0;\n    var tgtExists = cy.getElementById( tgtId ).length > 0;\n\n    if( srcExists || tgtExists ){\n      var jsons = this.jsons();\n\n      this.remove();\n\n      for( var i = 0; i < jsons.length; i++ ){\n        var json = jsons[i];\n\n        if( json.group === 'edges' ){\n          if( srcExists ){ json.data.source = srcId; }\n          if( tgtExists ){ json.data.target = tgtId; }\n        }\n      }\n\n      return cy.add( jsons );\n    }\n\n  } else if( struct.parent !== undefined ){ // move node to new parent\n    var parentId = struct.parent;\n    var parentExists = parentId === null || cy.getElementById( parentId ).length > 0;\n\n    if( parentExists ){\n      var jsons = this.jsons();\n      var descs = this.descendants();\n      var descsEtc = descs.merge( descs.add(this).connectedEdges() );\n\n      this.remove(); // NB: also removes descendants and their connected edges\n\n      for( var i = 0; i < this.length; i++ ){\n        var json = jsons[i];\n\n        if( json.group === 'nodes' ){\n          json.data.parent = parentId === null ? undefined : parentId;\n        }\n      }\n    }\n\n    return cy.add( jsons ).merge( descsEtc.restore() );\n  }\n\n  return this; // if nothing done\n};\n\n[\n  _dereq_('./algorithms'),\n  _dereq_('./animation'),\n  _dereq_('./class'),\n  _dereq_('./comparators'),\n  _dereq_('./compounds'),\n  _dereq_('./data'),\n  _dereq_('./degree'),\n  _dereq_('./dimensions'),\n  _dereq_('./events'),\n  _dereq_('./filter'),\n  _dereq_('./group'),\n  _dereq_('./index'),\n  _dereq_('./iteration'),\n  _dereq_('./layout'),\n  _dereq_('./style'),\n  _dereq_('./switch-functions'),\n  _dereq_('./traversing')\n].forEach(function( props ){\n  util.extend( elesfn, props );\n});\n\nmodule.exports = Collection;\n\n},{\"../is\":77,\"../util\":94,\"./algorithms\":9,\"./animation\":12,\"./class\":13,\"./comparators\":14,\"./compounds\":15,\"./data\":16,\"./degree\":17,\"./dimensions\":18,\"./element\":19,\"./events\":20,\"./filter\":21,\"./group\":22,\"./index\":23,\"./iteration\":24,\"./layout\":25,\"./style\":26,\"./switch-functions\":27,\"./traversing\":28}],24:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar zIndexSort = _dereq_('./zsort');\n\nvar elesfn = ({\n  each: function(fn){\n    if( is.fn(fn) ){\n      for(var i = 0; i < this.length; i++){\n        var ele = this[i];\n        var ret = fn.apply( ele, [ i, ele ] );\n\n        if( ret === false ){ break; } // exit each early on return false\n      }\n    }\n    return this;\n  },\n\n  forEach: function(fn, thisArg){\n    if( is.fn(fn) ){\n\n      for(var i = 0; i < this.length; i++){\n        var ele = this[i];\n        var ret = thisArg ? fn.apply( thisArg, [ ele, i, this ] ) : fn( ele, i, this );\n\n        if( ret === false ){ break; } // exit each early on return false\n      }\n    }\n\n    return this;\n  },\n\n  toArray: function(){\n    var array = [];\n\n    for(var i = 0; i < this.length; i++){\n      array.push( this[i] );\n    }\n\n    return array;\n  },\n\n  slice: function(start, end){\n    var array = [];\n    var thisSize = this.length;\n\n    if( end == null ){\n      end = thisSize;\n    }\n\n    if( start == null ){\n      start = 0;\n    }\n\n    if( start < 0 ){\n      start = thisSize + start;\n    }\n\n    if( end < 0 ){\n      end = thisSize + end;\n    }\n\n    for(var i = start; i >= 0 && i < end && i < thisSize; i++){\n      array.push( this[i] );\n    }\n\n    return this.spawn(array);\n  },\n\n  size: function(){\n    return this.length;\n  },\n\n  eq: function(i){\n    return this[i] || this.spawn();\n  },\n\n  first: function(){\n    return this[0] || this.spawn();\n  },\n\n  last: function(){\n    return this[ this.length - 1 ] || this.spawn();\n  },\n\n  empty: function(){\n    return this.length === 0;\n  },\n\n  nonempty: function(){\n    return !this.empty();\n  },\n\n  sort: function( sortFn ){\n    if( !is.fn( sortFn ) ){\n      return this;\n    }\n\n    var sorted = this.toArray().sort( sortFn );\n\n    return this.spawn(sorted);\n  },\n\n  sortByZIndex: function(){\n    return this.sort( zIndexSort );\n  },\n\n  zDepth: function(){\n    var ele = this[0];\n    if( !ele ){ return undefined; }\n\n    // var cy = ele.cy();\n    var _p = ele._private;\n    var group = _p.group;\n\n    if( group === 'nodes' ){\n      var depth = _p.data.parent ? ele.parents().size() : 0;\n\n      if( !ele.isParent() ){\n        return Number.MAX_VALUE; // childless nodes always on top\n      }\n\n      return depth;\n    } else {\n      var src = _p.source;\n      var tgt = _p.target;\n      var srcDepth = src.zDepth();\n      var tgtDepth = tgt.zDepth();\n\n      return Math.max( srcDepth, tgtDepth, 0 ); // depth of deepest parent\n    }\n  }\n});\n\nmodule.exports = elesfn;\n\n},{\"../is\":77,\"./zsort\":29}],25:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar util = _dereq_('../util');\n\nvar elesfn = ({\n\n  // using standard layout options, apply position function (w/ or w/o animation)\n  layoutPositions: function( layout, options, fn ){\n    var nodes = this.nodes();\n    var cy = this.cy();\n\n    layout.trigger({ type: 'layoutstart', layout: layout });\n\n    layout.animations = [];\n\n    if( options.animate ){\n      for( var i = 0; i < nodes.length; i++ ){\n        var node = nodes[i];\n        var lastNode = i === nodes.length - 1;\n\n        var newPos = fn.call( node, i, node );\n        var pos = node.position();\n\n        if( !is.number(pos.x) || !is.number(pos.y) ){\n          node.silentPosition({ x: 0, y: 0 });\n        }\n\n        var ani = node.animation({\n          position: newPos,\n          duration: options.animationDuration,\n          easing: options.animationEasing,\n          step: !lastNode ? undefined : function(){\n            if( options.fit ){\n              cy.fit( options.eles, options.padding );\n            }\n          },\n          complete: !lastNode ? undefined : function(){\n            if( options.zoom != null ){\n              cy.zoom( options.zoom );\n            }\n\n            if( options.pan ){\n              cy.pan( options.pan );\n            }\n\n            if( options.fit ){\n              cy.fit( options.eles, options.padding );\n            }\n\n            layout.one('layoutstop', options.stop);\n            layout.trigger({ type: 'layoutstop', layout: layout });\n          }\n        });\n\n        layout.animations.push( ani );\n\n        ani.play();\n      }\n\n      layout.one('layoutready', options.ready);\n      layout.trigger({ type: 'layoutready', layout: layout });\n    } else {\n      nodes.positions( fn );\n\n      if( options.fit ){\n        cy.fit( options.eles, options.padding );\n      }\n\n      if( options.zoom != null ){\n        cy.zoom( options.zoom );\n      }\n\n      if( options.pan ){\n        cy.pan( options.pan );\n      }\n\n      layout.one('layoutready', options.ready);\n      layout.trigger({ type: 'layoutready', layout: layout });\n\n      layout.one('layoutstop', options.stop);\n      layout.trigger({ type: 'layoutstop', layout: layout });\n    }\n\n    return this; // chaining\n  },\n\n  layout: function( options ){\n    var cy = this.cy();\n\n    cy.layout( util.extend({}, options, {\n      eles: this\n    }) );\n\n    return this;\n  },\n\n  makeLayout: function( options ){\n    var cy = this.cy();\n\n    return cy.makeLayout( util.extend({}, options, {\n      eles: this\n    }) );\n  }\n\n});\n\n// aliases:\nelesfn.createLayout = elesfn.makeLayout;\n\nmodule.exports = elesfn;\n\n},{\"../is\":77,\"../util\":94}],26:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\n\nvar elesfn = ({\n\n  // fully updates (recalculates) the style for the elements\n  updateStyle: function( notifyRenderer ){\n    var cy = this._private.cy;\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    if( cy._private.batchingStyle ){\n      var bEles = cy._private.batchStyleEles;\n\n      bEles.merge( this );\n\n      return this; // chaining and exit early when batching\n    }\n\n    var style = cy.style();\n    notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;\n\n    style.apply( this );\n\n    var updatedCompounds = this.updateCompoundBounds();\n    var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n\n    if( notifyRenderer ){\n      toNotify.rtrigger('style'); // let renderer know we changed style\n    } else {\n      toNotify.trigger('style'); // just fire the event\n    }\n    return this; // chaining\n  },\n\n  // just update the mappers in the elements' styles; cheaper than eles.updateStyle()\n  updateMappers: function( notifyRenderer ){\n    var cy = this._private.cy;\n    var style = cy.style();\n    notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    style.updateMappers( this );\n\n    var updatedCompounds = this.updateCompoundBounds();\n    var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n\n    if( notifyRenderer ){\n      toNotify.rtrigger('style'); // let renderer know we changed style\n    } else {\n      toNotify.trigger('style'); // just fire the event\n    }\n    return this; // chaining\n  },\n\n  // get the specified css property as a rendered value (i.e. on-screen value)\n  // or get the whole rendered style if no property specified (NB doesn't allow setting)\n  renderedCss: function( property ){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return this; }\n\n    var ele = this[0];\n\n    if( ele ){\n      var renstyle = ele.cy().style().getRenderedStyle( ele );\n\n      if( property === undefined ){\n        return renstyle;\n      } else {\n        return renstyle[ property ];\n      }\n    }\n  },\n\n  // read the calculated css style of the element or override the style (via a bypass)\n  css: function( name, value ){\n    var cy = this.cy();\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    var updateTransitions = false;\n    var style = cy.style();\n\n    if( is.plainObject(name) ){ // then extend the bypass\n      var props = name;\n      style.applyBypass( this, props, updateTransitions );\n\n      var updatedCompounds = this.updateCompoundBounds();\n      var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n      toNotify.rtrigger('style'); // let the renderer know we've updated style\n\n    } else if( is.string(name) ){\n\n      if( value === undefined ){ // then get the property from the style\n        var ele = this[0];\n\n        if( ele ){\n          return style.getStylePropertyValue( ele, name );\n        } else { // empty collection => can't get any value\n          return;\n        }\n\n      } else { // then set the bypass with the property value\n        style.applyBypass( this, name, value, updateTransitions );\n\n        var updatedCompounds = this.updateCompoundBounds();\n        var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n        toNotify.rtrigger('style'); // let the renderer know we've updated style\n      }\n\n    } else if( name === undefined ){\n      var ele = this[0];\n\n      if( ele ){\n        return style.getRawStyle( ele );\n      } else { // empty collection => can't get any value\n        return;\n      }\n    }\n\n    return this; // chaining\n  },\n\n  removeCss: function( names ){\n    var cy = this.cy();\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    var updateTransitions = false;\n    var style = cy.style();\n    var eles = this;\n\n    if( names === undefined ){\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        style.removeAllBypasses( ele, updateTransitions );\n      }\n    } else {\n      names = names.split(/\\s+/);\n\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        style.removeBypasses( ele, names, updateTransitions );\n      }\n    }\n\n    var updatedCompounds = this.updateCompoundBounds();\n    var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n    toNotify.rtrigger('style'); // let the renderer know we've updated style\n\n    return this; // chaining\n  },\n\n  show: function(){\n    this.css('display', 'element');\n    return this; // chaining\n  },\n\n  hide: function(){\n    this.css('display', 'none');\n    return this; // chaining\n  },\n\n  visible: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return true; }\n\n    var ele = this[0];\n    var hasCompoundNodes = cy.hasCompoundNodes();\n\n    if( ele ){\n      var style = ele._private.style;\n\n      if(\n        style['visibility'].value !== 'visible'\n        || style['display'].value !== 'element'\n      ){\n        return false;\n      }\n\n      if( ele._private.group === 'nodes' ){\n        if( !hasCompoundNodes ){ return true; }\n\n        var parents = ele._private.data.parent ? ele.parents() : null;\n\n        if( parents ){\n          for( var i = 0; i < parents.length; i++ ){\n            var parent = parents[i];\n            var pStyle = parent._private.style;\n            var pVis = pStyle['visibility'].value;\n            var pDis = pStyle['display'].value;\n\n            if( pVis !== 'visible' || pDis !== 'element' ){\n              return false;\n            }\n          }\n        }\n\n        return true;\n      } else {\n        var src = ele._private.source;\n        var tgt = ele._private.target;\n\n        return src.visible() && tgt.visible();\n      }\n\n    }\n  },\n\n  hidden: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return !ele.visible();\n    }\n  },\n\n  effectiveOpacity: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return 1; }\n\n    var hasCompoundNodes = cy.hasCompoundNodes();\n    var ele = this[0];\n\n    if( ele ){\n      var _p = ele._private;\n      var parentOpacity = _p.style.opacity.value;\n\n      if( !hasCompoundNodes ){ return parentOpacity; }\n\n      var parents = !_p.data.parent ? null : ele.parents();\n\n      if( parents ){\n        for( var i = 0; i < parents.length; i++ ){\n          var parent = parents[i];\n          var opacity = parent._private.style.opacity.value;\n\n          parentOpacity = opacity * parentOpacity;\n        }\n      }\n\n      return parentOpacity;\n    }\n  },\n\n  transparent: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return false; }\n\n    var ele = this[0];\n    var hasCompoundNodes = ele.cy().hasCompoundNodes();\n\n    if( ele ){\n      if( !hasCompoundNodes ){\n        return ele._private.style.opacity.value === 0;\n      } else {\n        return ele.effectiveOpacity() === 0;\n      }\n    }\n  },\n\n  isFullAutoParent: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return false; }\n\n    var ele = this[0];\n\n    if( ele ){\n      var autoW = ele._private.style['width'].value === 'auto';\n      var autoH = ele._private.style['height'].value === 'auto';\n\n      return ele.isParent() && autoW && autoH;\n    }\n  },\n\n  backgrounding: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return false; }\n\n    var ele = this[0];\n\n    return ele._private.backgrounding ? true : false;\n  }\n\n});\n\n\nelesfn.bypass = elesfn.style = elesfn.css;\nelesfn.renderedStyle = elesfn.renderedCss;\nelesfn.removeBypass = elesfn.removeStyle = elesfn.removeCss;\n\nmodule.exports = elesfn;\n\n},{\"../is\":77}],27:[function(_dereq_,module,exports){\n'use strict';\n\nvar elesfn = {};\n\nfunction defineSwitchFunction(params){\n  return function(){\n    var args = arguments;\n    var changedEles = [];\n\n    // e.g. cy.nodes().select( data, handler )\n    if( args.length === 2 ){\n      var data = args[0];\n      var handler = args[1];\n      this.bind( params.event, data, handler );\n    }\n\n    // e.g. cy.nodes().select( handler )\n    else if( args.length === 1 ){\n      var handler = args[0];\n      this.bind( params.event, handler );\n    }\n\n    // e.g. cy.nodes().select()\n    else if( args.length === 0 ){\n      for( var i = 0; i < this.length; i++ ){\n        var ele = this[i];\n        var able = !params.ableField || ele._private[params.ableField];\n        var changed = ele._private[params.field] != params.value;\n\n        if( params.overrideAble ){\n          var overrideAble = params.overrideAble(ele);\n\n          if( overrideAble !== undefined ){\n            able = overrideAble;\n\n            if( !overrideAble ){ return this; } // to save cycles assume not able for all on override\n          }\n        }\n\n        if( able ){\n          ele._private[params.field] = params.value;\n\n          if( changed ){\n            changedEles.push( ele );\n          }\n        }\n      }\n\n      var changedColl = this.spawn( changedEles );\n      changedColl.updateStyle(); // change of state => possible change of style\n      changedColl.trigger( params.event );\n    }\n\n    return this;\n  };\n}\n\nfunction defineSwitchSet( params ){\n  elesfn[ params.field ] = function(){\n    var ele = this[0];\n\n    if( ele ){\n      if( params.overrideField ){\n        var val = params.overrideField(ele);\n\n        if( val !== undefined ){\n          return val;\n        }\n      }\n\n      return ele._private[ params.field ];\n    }\n  };\n\n  elesfn[ params.on ] = defineSwitchFunction({\n    event: params.on,\n    field: params.field,\n    ableField: params.ableField,\n    overrideAble: params.overrideAble,\n    value: true\n  });\n\n  elesfn[ params.off ] = defineSwitchFunction({\n    event: params.off,\n    field: params.field,\n    ableField: params.ableField,\n    overrideAble: params.overrideAble,\n    value: false\n  });\n}\n\ndefineSwitchSet({\n  field: 'locked',\n  overrideField: function(ele){\n    return ele.cy().autolock() ? true : undefined;\n  },\n  on: 'lock',\n  off: 'unlock'\n});\n\ndefineSwitchSet({\n  field: 'grabbable',\n  overrideField: function(ele){\n    return ele.cy().autoungrabify() ? false : undefined;\n  },\n  on: 'grabify',\n  off: 'ungrabify'\n});\n\ndefineSwitchSet({\n  field: 'selected',\n  ableField: 'selectable',\n  overrideAble: function(ele){\n    return ele.cy().autounselectify() ? false : undefined;\n  },\n  on: 'select',\n  off: 'unselect'\n});\n\ndefineSwitchSet({\n  field: 'selectable',\n  overrideField: function(ele){\n    return ele.cy().autounselectify() ? false : undefined;\n  },\n  on: 'selectify',\n  off: 'unselectify'\n});\n\nelesfn.deselect = elesfn.unselect;\n\nelesfn.grabbed = function(){\n  var ele = this[0];\n  if( ele ){\n    return ele._private.grabbed;\n  }\n};\n\ndefineSwitchSet({\n  field: 'active',\n  on: 'activate',\n  off: 'unactivate'\n});\n\nelesfn.inactive = function(){\n  var ele = this[0];\n  if( ele ){\n    return !ele._private.active;\n  }\n};\n\nmodule.exports = elesfn;\n\n},{}],28:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\nvar elesfn = {};\n\nutil.extend(elesfn, {\n  // get the root nodes in the DAG\n  roots: function( selector ){\n    var eles = this;\n    var roots = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      if( !ele.isNode() ){\n        continue;\n      }\n\n      var hasEdgesPointingIn = ele.connectedEdges(function(){\n        return this.data('target') === ele.id() && this.data('source') !== ele.id();\n      }).length > 0;\n\n      if( !hasEdgesPointingIn ){\n        roots.push( ele );\n      }\n    }\n\n    return this.spawn( roots, { unique: true } ).filter( selector );\n  },\n\n  // get the leaf nodes in the DAG\n  leaves: function( selector ){\n    var eles = this;\n    var leaves = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      if( !ele.isNode() ){\n        continue;\n      }\n\n      var hasEdgesPointingOut = ele.connectedEdges(function(){\n        return this.data('source') === ele.id() && this.data('target') !== ele.id();\n      }).length > 0;\n\n      if( !hasEdgesPointingOut ){\n        leaves.push( ele );\n      }\n    }\n\n    return this.spawn( leaves, { unique: true } ).filter( selector );\n  },\n\n  // normally called children in graph theory\n  // these nodes =edges=> outgoing nodes\n  outgoers: function( selector ){\n    var eles = this;\n    var oEles = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var eleId = ele.id();\n\n      if( !ele.isNode() ){ continue; }\n\n      var edges = ele._private.edges;\n      for( var j = 0; j < edges.length; j++ ){\n        var edge = edges[j];\n        var srcId = edge._private.data.source;\n        var tgtId = edge._private.data.target;\n\n        if( srcId === eleId && tgtId !== eleId ){\n          oEles.push( edge );\n          oEles.push( edge.target()[0] );\n        }\n      }\n    }\n\n    return this.spawn( oEles, { unique: true } ).filter( selector );\n  },\n\n  // aka DAG descendants\n  successors: function( selector ){\n    var eles = this;\n    var sEles = [];\n    var sElesIds = {};\n\n    for(;;){\n      var outgoers = eles.outgoers();\n\n      if( outgoers.length === 0 ){ break; } // done if no outgoers left\n\n      var newOutgoers = false;\n      for( var i = 0; i < outgoers.length; i++ ){\n        var outgoer = outgoers[i];\n        var outgoerId = outgoer.id();\n\n        if( !sElesIds[ outgoerId ] ){\n          sElesIds[ outgoerId ] = true;\n          sEles.push( outgoer );\n          newOutgoers = true;\n        }\n      }\n\n      if( !newOutgoers ){ break; } // done if touched all outgoers already\n\n      eles = outgoers;\n    }\n\n    return this.spawn( sEles, { unique: true } ).filter( selector );\n  },\n\n  // normally called parents in graph theory\n  // these nodes <=edges= incoming nodes\n  incomers: function( selector ){\n    var eles = this;\n    var oEles = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var eleId = ele.id();\n\n      if( !ele.isNode() ){ continue; }\n\n      var edges = ele._private.edges;\n      for( var j = 0; j < edges.length; j++ ){\n        var edge = edges[j];\n        var srcId = edge._private.data.source;\n        var tgtId = edge._private.data.target;\n\n        if( tgtId === eleId && srcId !== eleId ){\n          oEles.push( edge );\n          oEles.push( edge.source()[0] );\n        }\n      }\n    }\n\n    return this.spawn( oEles, { unique: true } ).filter( selector );\n  },\n\n  // aka DAG ancestors\n  predecessors: function( selector ){\n    var eles = this;\n    var pEles = [];\n    var pElesIds = {};\n\n    for(;;){\n      var incomers = eles.incomers();\n\n      if( incomers.length === 0 ){ break; } // done if no incomers left\n\n      var newIncomers = false;\n      for( var i = 0; i < incomers.length; i++ ){\n        var incomer = incomers[i];\n        var incomerId = incomer.id();\n\n        if( !pElesIds[ incomerId ] ){\n          pElesIds[ incomerId ] = true;\n          pEles.push( incomer );\n          newIncomers = true;\n        }\n      }\n\n      if( !newIncomers ){ break; } // done if touched all incomers already\n\n      eles = incomers;\n    }\n\n    return this.spawn( pEles, { unique: true } ).filter( selector );\n  }\n});\n\n\n// Neighbourhood functions\n//////////////////////////\n\nutil.extend(elesfn, {\n  neighborhood: function(selector){\n    var elements = [];\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){ // for all nodes\n      var node = nodes[i];\n      var connectedEdges = node.connectedEdges();\n\n      // for each connected edge, add the edge and the other node\n      for( var j = 0; j < connectedEdges.length; j++ ){\n        var edge = connectedEdges[j];\n        var src = edge._private.source;\n        var tgt = edge._private.target;\n        var otherNode = node === src ? tgt : src;\n\n        // need check in case of loop\n        if( otherNode.length > 0 ){\n          elements.push( otherNode[0] ); // add node 1 hop away\n        }\n\n        // add connected edge\n        elements.push( edge[0] );\n      }\n\n    }\n\n    return ( this.spawn( elements, { unique: true } ) ).filter( selector );\n  },\n\n  closedNeighborhood: function(selector){\n    return this.neighborhood().add( this ).filter( selector );\n  },\n\n  openNeighborhood: function(selector){\n    return this.neighborhood( selector );\n  }\n});\n\n// aliases\nelesfn.neighbourhood = elesfn.neighborhood;\nelesfn.closedNeighbourhood = elesfn.closedNeighborhood;\nelesfn.openNeighbourhood = elesfn.openNeighborhood;\n\n// Edge functions\n/////////////////\n\nutil.extend(elesfn, {\n  source: function( selector ){\n    var ele = this[0];\n    var src;\n\n    if( ele ){\n      src = ele._private.source;\n    }\n\n    return src && selector ? src.filter( selector ) : src;\n  },\n\n  target: function( selector ){\n    var ele = this[0];\n    var tgt;\n\n    if( ele ){\n      tgt = ele._private.target;\n    }\n\n    return tgt && selector ? tgt.filter( selector ) : tgt;\n  },\n\n  sources: defineSourceFunction({\n    attr: 'source'\n  }),\n\n  targets: defineSourceFunction({\n    attr: 'target'\n  })\n});\n\nfunction defineSourceFunction( params ){\n  return function( selector ){\n    var sources = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      var src = ele._private[ params.attr ];\n\n      if( src ){\n        sources.push( src );\n      }\n    }\n\n    return this.spawn( sources, { unique: true } ).filter( selector );\n  };\n}\n\nutil.extend(elesfn, {\n  edgesWith: defineEdgesWithFunction(),\n\n  edgesTo: defineEdgesWithFunction({\n    thisIs: 'source'\n  })\n});\n\nfunction defineEdgesWithFunction( params ){\n\n  return function edgesWithImpl( otherNodes ){\n    var elements = [];\n    var cy = this._private.cy;\n    var p = params || {};\n\n    // get elements if a selector is specified\n    if( is.string(otherNodes) ){\n      otherNodes = cy.$( otherNodes );\n    }\n\n    var thisIds = this._private.ids;\n    var otherIds = otherNodes._private.ids;\n\n    for( var h = 0; h < otherNodes.length; h++ ){\n      var edges = otherNodes[h]._private.edges;\n\n      for( var i = 0; i < edges.length; i++ ){\n        var edge = edges[i];\n        var edgeData = edge._private.data;\n        var thisToOther = thisIds[ edgeData.source ] && otherIds[ edgeData.target ];\n        var otherToThis = otherIds[ edgeData.source ] && thisIds[ edgeData.target ];\n        var edgeConnectsThisAndOther = thisToOther || otherToThis;\n\n        if( !edgeConnectsThisAndOther ){ continue; }\n\n        if( p.thisIs ){\n          if( p.thisIs === 'source' && !thisToOther ){ continue; }\n\n          if( p.thisIs === 'target' && !otherToThis ){ continue; }\n        }\n\n        elements.push( edge );\n      }\n    }\n\n    return this.spawn( elements, { unique: true } );\n  };\n}\n\nutil.extend(elesfn, {\n  connectedEdges: function( selector ){\n    var retEles = [];\n\n    var eles = this;\n    for( var i = 0; i < eles.length; i++ ){\n      var node = eles[i];\n      if( !node.isNode() ){ continue; }\n\n      var edges = node._private.edges;\n\n      for( var j = 0; j < edges.length; j++ ){\n        var edge = edges[j];\n        retEles.push( edge );\n      }\n    }\n\n    return this.spawn( retEles, { unique: true } ).filter( selector );\n  },\n\n  connectedNodes: function( selector ){\n    var retEles = [];\n\n    var eles = this;\n    for( var i = 0; i < eles.length; i++ ){\n      var edge = eles[i];\n      if( !edge.isEdge() ){ continue; }\n\n      retEles.push( edge.source()[0] );\n      retEles.push( edge.target()[0] );\n    }\n\n    return this.spawn( retEles, { unique: true } ).filter( selector );\n  },\n\n  parallelEdges: defineParallelEdgesFunction(),\n\n  codirectedEdges: defineParallelEdgesFunction({\n    codirected: true\n  })\n});\n\nfunction defineParallelEdgesFunction(params){\n  var defaults = {\n    codirected: false\n  };\n  params = util.extend({}, defaults, params);\n\n  return function( selector ){\n    var elements = [];\n    var edges = this.edges();\n    var p = params;\n\n    // look at all the edges in the collection\n    for( var i = 0; i < edges.length; i++ ){\n      var edge1 = edges[i];\n      var src1 = edge1.source()[0];\n      var srcid1 = src1.id();\n      var tgt1 = edge1.target()[0];\n      var tgtid1 = tgt1.id();\n      var srcEdges1 = src1._private.edges;\n\n      // look at edges connected to the src node of this edge\n      for( var j = 0; j < srcEdges1.length; j++ ){\n        var edge2 = srcEdges1[j];\n        var edge2data = edge2._private.data;\n        var tgtid2 = edge2data.target;\n        var srcid2 = edge2data.source;\n\n        var codirected = tgtid2 === tgtid1 && srcid2 === srcid1;\n        var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2;\n\n        if( (p.codirected && codirected) || (!p.codirected && (codirected || oppdirected)) ){\n          elements.push( edge2 );\n        }\n      }\n    }\n\n    return this.spawn( elements, { unique: true } ).filter( selector );\n  };\n\n}\n\n// Misc functions\n/////////////////\n\nutil.extend(elesfn, {\n  components: function(){\n    var cy = this.cy();\n    var visited = cy.collection();\n    var unvisited = this.nodes();\n    var components = [];\n\n    var visitInComponent = function( node, component ){\n      visited.merge( node );\n      unvisited.unmerge( node );\n      component.merge( node );\n    };\n\n    do {\n      var component = cy.collection();\n      components.push( component );\n\n      var root = unvisited[0];\n      visitInComponent( root, component );\n\n      this.bfs({\n        directed: false,\n        roots: root,\n        visit: function( i, depth, v, e, u ){\n          visitInComponent( v, component );\n        }\n      });\n\n    } while( unvisited.length > 0 );\n\n    return components.map(function( component ){\n      return component.closedNeighborhood(); // add the edges\n    });\n  }\n});\n\nmodule.exports = elesfn;\n\n},{\"../is\":77,\"../util\":94}],29:[function(_dereq_,module,exports){\n'use strict';\n\nvar zIndexSort = function( a, b ){\n  var cy = a.cy();\n  var a_p = a._private;\n  var b_p = b._private;\n  var zDiff = a_p.style['z-index'].value - b_p.style['z-index'].value;\n  var depthA = 0;\n  var depthB = 0;\n  var hasCompoundNodes = cy.hasCompoundNodes();\n  var aIsNode = a_p.group === 'nodes';\n  var aIsEdge = a_p.group === 'edges';\n  var bIsNode = b_p.group === 'nodes';\n  var bIsEdge = b_p.group === 'edges';\n\n  // no need to calculate element depth if there is no compound node\n  if( hasCompoundNodes ){\n    depthA = a.zDepth();\n    depthB = b.zDepth();\n  }\n\n  var depthDiff = depthA - depthB;\n  var sameDepth = depthDiff === 0;\n\n  if( sameDepth ){\n\n    if( aIsNode && bIsEdge ){\n      return 1; // 'a' is a node, it should be drawn later\n\n    } else if( aIsEdge && bIsNode ){\n      return -1; // 'a' is an edge, it should be drawn first\n\n    } else { // both nodes or both edges\n      if( zDiff === 0 ){ // same z-index => compare indices in the core (order added to graph w/ last on top)\n        return a_p.index - b_p.index;\n      } else {\n        return zDiff;\n      }\n    }\n\n  // elements on different level\n  } else {\n    return depthDiff; // deeper element should be drawn later\n  }\n\n};\n\nmodule.exports = zIndexSort;\n\n},{}],30:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar util = _dereq_('../util');\nvar Collection = _dereq_('../collection');\nvar Element = _dereq_('../collection/element');\nvar window = _dereq_('../window');\nvar document = window ? window.document : null;\nvar NullRenderer = _dereq_('../extensions/renderer/null');\n\nvar corefn = {\n  add: function(opts){\n\n    var elements;\n    var cy = this;\n\n    // add the elements\n    if( is.elementOrCollection(opts) ){\n      var eles = opts;\n\n      if( eles._private.cy === cy ){ // same instance => just restore\n        elements = eles.restore();\n\n      } else { // otherwise, copy from json\n        var jsons = [];\n\n        for( var i = 0; i < eles.length; i++ ){\n          var ele = eles[i];\n          jsons.push( ele.json() );\n        }\n\n        elements = new Collection( cy, jsons );\n      }\n    }\n\n    // specify an array of options\n    else if( is.array(opts) ){\n      var jsons = opts;\n\n      elements = new Collection(cy, jsons);\n    }\n\n    // specify via opts.nodes and opts.edges\n    else if( is.plainObject(opts) && (is.array(opts.nodes) || is.array(opts.edges)) ){\n      var elesByGroup = opts;\n      var jsons = [];\n\n      var grs = ['nodes', 'edges'];\n      for( var i = 0, il = grs.length; i < il; i++ ){\n        var group = grs[i];\n        var elesArray = elesByGroup[group];\n\n        if( is.array(elesArray) ){\n\n          for( var j = 0, jl = elesArray.length; j < jl; j++ ){\n            var json = util.extend( { group: group }, elesArray[j] );\n\n            jsons.push( json );\n          }\n        }\n      }\n\n      elements = new Collection(cy, jsons);\n    }\n\n    // specify options for one element\n    else {\n      var json = opts;\n      elements = (new Element( cy, json )).collection();\n    }\n\n    return elements;\n  },\n\n  remove: function(collection){\n    if( is.elementOrCollection(collection) ){\n      collection = collection;\n    } else if( is.string(collection) ){\n      var selector = collection;\n      collection = this.$( selector );\n    }\n\n    return collection.remove();\n  },\n\n  load: function(elements, onload, ondone){\n    var cy = this;\n\n    cy.notifications(false);\n\n    // remove old elements\n    var oldEles = cy.elements();\n    if( oldEles.length > 0 ){\n      oldEles.remove();\n    }\n\n    if( elements != null ){\n      if( is.plainObject(elements) || is.array(elements) ){\n        cy.add( elements );\n      }\n    }\n\n    cy.one('layoutready', function(e){\n      cy.notifications(true);\n      cy.trigger(e); // we missed this event by turning notifications off, so pass it on\n\n      cy.notify({\n        type: 'load',\n        collection: cy.elements()\n      });\n\n      cy.one('load', onload);\n      cy.trigger('load');\n    }).one('layoutstop', function(){\n      cy.one('done', ondone);\n      cy.trigger('done');\n    });\n\n    var layoutOpts = util.extend({}, cy._private.options.layout);\n    layoutOpts.eles = cy.$();\n\n    cy.layout( layoutOpts );\n\n    return this;\n  }\n};\n\nmodule.exports = corefn;\n\n},{\"../collection\":23,\"../collection/element\":19,\"../extensions/renderer/null\":73,\"../is\":77,\"../util\":94,\"../window\":100}],31:[function(_dereq_,module,exports){\n'use strict';\n\nvar define = _dereq_('../define');\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\nvar corefn = ({\n\n  // pull in animation functions\n  animate: define.animate(),\n  animation: define.animation(),\n  animated: define.animated(),\n  clearQueue: define.clearQueue(),\n  delay: define.delay(),\n  delayAnimation: define.delayAnimation(),\n  stop: define.stop(),\n\n  addToAnimationPool: function( eles ){\n    var cy = this;\n\n    if( !cy.styleEnabled() ){ return; } // save cycles when no style used\n\n    cy._private.aniEles.merge( eles );\n  },\n\n  stopAnimationLoop: function(){\n    this._private.animationsRunning = false;\n  },\n\n  startAnimationLoop: function(){\n    var cy = this;\n\n    cy._private.animationsRunning = true;\n\n    if( !cy.styleEnabled() ){ return; } // save cycles when no style used\n\n    // NB the animation loop will exec in headless environments if style enabled\n    // and explicit cy.destroy() is necessary to stop the loop\n\n    function globalAnimationStep(){\n      if( !cy._private.animationsRunning ){ return; }\n\n      util.requestAnimationFrame(function(now){\n        handleElements(now);\n        globalAnimationStep();\n      });\n    }\n\n    globalAnimationStep(); // first call\n\n    function handleElements( now ){\n      var eles = cy._private.aniEles;\n      var doneEles = [];\n\n      function handleElement( ele, isCore ){\n        var _p = ele._private;\n        var current = _p.animation.current;\n        var queue = _p.animation.queue;\n        var ranAnis = false;\n\n        // if nothing currently animating, get something from the queue\n        if( current.length === 0 ){\n          var next = queue.shift();\n\n          if( next ){\n            current.push( next );\n          }\n        }\n\n        var callbacks = function( callbacks ){\n          for( var j = callbacks.length - 1; j >= 0; j-- ){\n            var cb = callbacks[j];\n\n            cb();\n          }\n\n          callbacks.splice( 0, callbacks.length );\n        };\n\n        // step and remove if done\n        for( var i = current.length - 1; i >= 0; i-- ){\n          var ani = current[i];\n          var ani_p = ani._private;\n\n          if( ani_p.stopped ){\n            current.splice( i, 1 );\n\n            ani_p.hooked = false;\n            ani_p.playing = false;\n            ani_p.started = false;\n\n            callbacks( ani_p.frames );\n\n            continue;\n          }\n\n          if( !ani_p.playing && !ani_p.applying ){ continue; }\n\n          // an apply() while playing shouldn't do anything\n          if( ani_p.playing && ani_p.applying ){\n            ani_p.applying = false;\n          }\n\n          if( !ani_p.started ){\n            startAnimation( ele, ani, now );\n          }\n\n          step( ele, ani, now, isCore );\n\n          if( ani_p.applying ){\n            ani_p.applying = false;\n          }\n\n          callbacks( ani_p.frames );\n\n          if( ani.completed() ){\n            current.splice(i, 1);\n\n            ani_p.hooked = false;\n            ani_p.playing = false;\n            ani_p.started = false;\n\n            callbacks( ani_p.completes );\n          }\n\n          ranAnis = true;\n        }\n\n        if( !isCore && current.length === 0 && queue.length === 0 ){\n          doneEles.push( ele );\n        }\n\n        return ranAnis;\n      } // handleElement\n\n      // handle all eles\n      var ranEleAni = false;\n      for( var e = 0; e < eles.length; e++ ){\n        var ele = eles[e];\n        var handledThisEle = handleElement( ele );\n\n        ranEleAni = ranEleAni || handledThisEle;\n      } // each element\n\n      var ranCoreAni = handleElement( cy, true );\n\n      // notify renderer\n      if( ranEleAni || ranCoreAni ){\n        var toNotify;\n\n        if( eles.length > 0 ){\n          var updatedEles = eles.updateCompoundBounds();\n          toNotify = updatedEles.length > 0 ? eles.add( updatedEles ) : eles;\n        }\n\n        cy.notify({\n          type: 'draw',\n          collection: toNotify\n        });\n      }\n\n      // remove elements from list of currently animating if its queues are empty\n      eles.unmerge( doneEles );\n\n    } // handleElements\n\n    function startAnimation( self, ani, now ){\n      var isCore = is.core( self );\n      var isEles = !isCore;\n      var ele = self;\n      var style = cy._private.style;\n      var ani_p = ani._private;\n\n      if( isEles ){\n        var pos = ele._private.position;\n\n        ani_p.startPosition = ani_p.startPosition || {\n          x: pos.x,\n          y: pos.y\n        };\n\n        ani_p.startStyle = ani_p.startStyle || style.getValueStyle( ele );\n      }\n\n      if( isCore ){\n        var pan = cy._private.pan;\n\n        ani_p.startPan = ani_p.startPan || {\n          x: pan.x,\n          y: pan.y\n        };\n\n        ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom;\n      }\n\n      ani_p.started = true;\n      ani_p.startTime = now - ani_p.progress * ani_p.duration;\n    }\n\n    function step( self, ani, now, isCore ){\n      var style = cy._private.style;\n      var isEles = !isCore;\n      var _p = self._private;\n      var ani_p = ani._private;\n      var pEasing = ani_p.easing;\n      var startTime = ani_p.startTime;\n\n      if( !ani_p.easingImpl ){\n\n        if( pEasing == null ){ // use default\n          ani_p.easingImpl = easings['linear'];\n\n        } else { // then define w/ name\n          var easingVals;\n\n          if( is.string( pEasing ) ){\n            var easingProp = style.parse('transition-timing-function', pEasing);\n\n            easingVals = easingProp.value;\n\n          } else { // then assume preparsed array\n            easingVals = pEasing;\n          }\n\n          var name, args;\n\n          if( is.string( easingVals ) ){\n            name = easingVals;\n            args = [];\n          } else {\n            name = easingVals[1];\n            args = easingVals.slice(2).map(function(n){ return +n; });\n          }\n\n          if( args.length > 0 ){ // create with args\n            if( name === 'spring' ){\n              args.push( ani_p.duration ); // need duration to generate spring\n            }\n\n            ani_p.easingImpl = easings[ name ].apply( null, args );\n          } else { // static impl by name\n            ani_p.easingImpl = easings[ name ];\n          }\n        }\n\n      }\n\n      var easing = ani_p.easingImpl;\n      var percent;\n\n      if( ani_p.duration === 0 ){\n        percent = 1;\n      } else {\n        percent = (now - startTime) / ani_p.duration;\n      }\n\n      if( ani_p.applying ){\n        percent = ani_p.progress;\n      }\n\n      if( percent < 0 ){\n        percent = 0;\n      } else if( percent > 1 ){\n        percent = 1;\n      }\n\n      if( ani_p.delay == null ){ // then update\n\n        var startPos = ani_p.startPosition;\n        var endPos = ani_p.position;\n        var pos = _p.position;\n        if( endPos && isEles ){\n          if( valid( startPos.x, endPos.x ) ){\n            pos.x = ease( startPos.x, endPos.x, percent, easing );\n          }\n\n          if( valid( startPos.y, endPos.y ) ){\n            pos.y = ease( startPos.y, endPos.y, percent, easing );\n          }\n        }\n\n        var startPan = ani_p.startPan;\n        var endPan = ani_p.pan;\n        var pan = _p.pan;\n        var animatingPan = endPan != null && isCore;\n        if( animatingPan ){\n          if( valid( startPan.x, endPan.x ) ){\n            pan.x = ease( startPan.x, endPan.x, percent, easing );\n          }\n\n          if( valid( startPan.y, endPan.y ) ){\n            pan.y = ease( startPan.y, endPan.y, percent, easing );\n          }\n\n          self.trigger('pan');\n        }\n\n        var startZoom = ani_p.startZoom;\n        var endZoom = ani_p.zoom;\n        var animatingZoom = endZoom != null && isCore;\n        if( animatingZoom ){\n          if( valid( startZoom, endZoom ) ){\n            _p.zoom = ease( startZoom, endZoom, percent, easing );\n          }\n\n          self.trigger('zoom');\n        }\n\n        if( animatingPan || animatingZoom ){\n          self.trigger('viewport');\n        }\n\n        var props = ani_p.style;\n        if( props && isEles ){\n\n          for( var i = 0; i < props.length; i++ ){\n            var prop = props[i];\n            var name = prop.name;\n            var end = prop;\n\n            var start = ani_p.startStyle[ name ];\n            var easedVal = ease( start, end, percent, easing );\n\n            style.overrideBypass( self, name, easedVal );\n          } // for props\n\n        } // if\n\n      }\n\n      if( is.fn(ani_p.step) ){\n        ani_p.step.apply( self, [ now ] );\n      }\n\n      ani_p.progress = percent;\n\n      return percent;\n    }\n\n    function valid(start, end){\n      if( start == null || end == null ){\n        return false;\n      }\n\n      if( is.number(start) && is.number(end) ){\n        return true;\n      } else if( (start) && (end) ){\n        return true;\n      }\n\n      return false;\n    }\n\n    // assumes p0 = 0, p3 = 1\n    function evalCubicBezier( p1, p2, t ){\n      var one_t = 1 - t;\n      var tsq = t*t;\n\n      return ( 3 * one_t * one_t * t * p1 ) + ( 3 * one_t * tsq * p2 ) + tsq * t;\n    }\n\n    function cubicBezier( p1, p2 ){\n      return function( start, end, percent ){\n        return start + (end - start) * evalCubicBezier( p1, p2, percent );\n      };\n    }\n\n    /* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */\n    /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass\n       then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */\n    var generateSpringRK4 = (function () {\n        function springAccelerationForState (state) {\n            return (-state.tension * state.x) - (state.friction * state.v);\n        }\n\n        function springEvaluateStateWithDerivative (initialState, dt, derivative) {\n            var state = {\n                x: initialState.x + derivative.dx * dt,\n                v: initialState.v + derivative.dv * dt,\n                tension: initialState.tension,\n                friction: initialState.friction\n            };\n\n            return { dx: state.v, dv: springAccelerationForState(state) };\n        }\n\n        function springIntegrateState (state, dt) {\n            var a = {\n                    dx: state.v,\n                    dv: springAccelerationForState(state)\n                },\n                b = springEvaluateStateWithDerivative(state, dt * 0.5, a),\n                c = springEvaluateStateWithDerivative(state, dt * 0.5, b),\n                d = springEvaluateStateWithDerivative(state, dt, c),\n                dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),\n                dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);\n\n            state.x = state.x + dxdt * dt;\n            state.v = state.v + dvdt * dt;\n\n            return state;\n        }\n\n        return function springRK4Factory (tension, friction, duration) {\n\n            var initState = {\n                    x: -1,\n                    v: 0,\n                    tension: null,\n                    friction: null\n                },\n                path = [0],\n                time_lapsed = 0,\n                tolerance = 1 / 10000,\n                DT = 16 / 1000,\n                have_duration, dt, last_state;\n\n            tension = parseFloat(tension) || 500;\n            friction = parseFloat(friction) || 20;\n            duration = duration || null;\n\n            initState.tension = tension;\n            initState.friction = friction;\n\n            have_duration = duration !== null;\n\n            /* Calculate the actual time it takes for this animation to complete with the provided conditions. */\n            if (have_duration) {\n                /* Run the simulation without a duration. */\n                time_lapsed = springRK4Factory(tension, friction);\n                /* Compute the adjusted time delta. */\n                dt = time_lapsed / duration * DT;\n            } else {\n                dt = DT;\n            }\n\n            while (true) {\n                /* Next/step function .*/\n                last_state = springIntegrateState(last_state || initState, dt);\n                /* Store the position. */\n                path.push(1 + last_state.x);\n                time_lapsed += 16;\n                /* If the change threshold is reached, break. */\n                if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {\n                    break;\n                }\n            }\n\n            /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the\n               computed path and returns a snapshot of the position according to a given percentComplete. */\n            return !have_duration ? time_lapsed : function(percentComplete) { return path[ (percentComplete * (path.length - 1)) | 0 ]; };\n        };\n    }());\n\n    var easings = {\n      'linear': function( start, end, percent ){\n        return start + (end - start) * percent;\n      },\n\n      // default easings\n      'ease': cubicBezier( 0.25, 0.1, 0.25, 1 ),\n      'ease-in': cubicBezier( 0.42, 0, 1, 1 ),\n      'ease-out': cubicBezier( 0, 0, 0.58, 1 ),\n      'ease-in-out': cubicBezier( 0.42, 0, 0.58, 1 ),\n\n      // sine\n      'ease-in-sine': cubicBezier( 0.47, 0, 0.745, 0.715 ),\n      'ease-out-sine': cubicBezier( 0.39, 0.575, 0.565, 1 ),\n      'ease-in-out-sine': cubicBezier( 0.445, 0.05, 0.55, 0.95 ),\n\n      // quad\n      'ease-in-quad': cubicBezier( 0.55, 0.085, 0.68, 0.53 ),\n      'ease-out-quad': cubicBezier( 0.25, 0.46, 0.45, 0.94 ),\n      'ease-in-out-quad': cubicBezier( 0.455, 0.03, 0.515, 0.955 ),\n\n      // cubic\n      'ease-in-cubic': cubicBezier( 0.55, 0.055, 0.675, 0.19 ),\n      'ease-out-cubic': cubicBezier( 0.215, 0.61, 0.355, 1 ),\n      'ease-in-out-cubic': cubicBezier( 0.645, 0.045, 0.355, 1 ),\n\n      // quart\n      'ease-in-quart': cubicBezier( 0.895, 0.03, 0.685, 0.22 ),\n      'ease-out-quart': cubicBezier( 0.165, 0.84, 0.44, 1 ),\n      'ease-in-out-quart': cubicBezier( 0.77, 0, 0.175, 1 ),\n\n      // quint\n      'ease-in-quint': cubicBezier( 0.755, 0.05, 0.855, 0.06 ),\n      'ease-out-quint': cubicBezier( 0.23, 1, 0.32, 1 ),\n      'ease-in-out-quint': cubicBezier( 0.86, 0, 0.07, 1 ),\n\n      // expo\n      'ease-in-expo': cubicBezier( 0.95, 0.05, 0.795, 0.035 ),\n      'ease-out-expo': cubicBezier( 0.19, 1, 0.22, 1 ),\n      'ease-in-out-expo': cubicBezier( 1, 0, 0, 1 ),\n\n      // circ\n      'ease-in-circ': cubicBezier( 0.6, 0.04, 0.98, 0.335 ),\n      'ease-out-circ': cubicBezier( 0.075, 0.82, 0.165, 1 ),\n      'ease-in-out-circ': cubicBezier( 0.785, 0.135, 0.15, 0.86 ),\n\n\n      // user param easings...\n\n      'spring': function( tension, friction, duration ){\n        var spring = generateSpringRK4( tension, friction, duration );\n\n        return function( start, end, percent ){\n          return start + (end - start) * spring( percent );\n        };\n      },\n\n      'cubic-bezier': function( x1, y1, x2, y2 ){\n        return cubicBezier( x1, y1, x2, y2 );\n      }\n    };\n\n    function ease( startProp, endProp, percent, easingFn ){\n      if( percent < 0 ){\n        percent = 0;\n      } else if( percent > 1 ){\n        percent = 1;\n      }\n\n      var start, end;\n\n      if( startProp.pfValue != null || startProp.value != null ){\n        start = startProp.pfValue != null ? startProp.pfValue : startProp.value;\n      } else {\n        start = startProp;\n      }\n\n      if( endProp.pfValue != null || endProp.value != null ){\n        end = endProp.pfValue != null ? endProp.pfValue : endProp.value;\n      } else {\n        end = endProp;\n      }\n\n      if( is.number(start) && is.number(end) ){\n        return easingFn( start, end, percent );\n\n      } else if( is.array(start) && is.array(end) ){\n        var easedArr = [];\n\n        for( var i = 0; i < end.length; i++ ){\n          var si = start[i];\n          var ei = end[i];\n\n          if( si != null && ei != null ){\n            var val = easingFn(si, ei, percent);\n\n            if( startProp.roundValue ){ val = Math.round( val ); }\n\n            easedArr.push( val );\n          } else {\n            easedArr.push( ei );\n          }\n        }\n\n        return easedArr;\n      }\n\n      return undefined;\n    }\n\n  }\n\n});\n\nmodule.exports = corefn;\n\n},{\"../define\":41,\"../is\":77,\"../util\":94}],32:[function(_dereq_,module,exports){\n'use strict';\n\nvar define = _dereq_('../define');\n\nvar corefn = ({\n  on: define.on(), // .on( events [, selector] [, data], handler)\n  one: define.on({ unbindSelfOnTrigger: true }),\n  once: define.on({ unbindAllBindersOnTrigger: true }),\n  off: define.off(), // .off( events [, selector] [, handler] )\n  trigger: define.trigger() // .trigger( events [, extraParams] )\n});\n\ndefine.eventAliasesOn( corefn );\n\nmodule.exports = corefn;\n\n},{\"../define\":41}],33:[function(_dereq_,module,exports){\n'use strict';\n\nvar corefn = ({\n\n  png: function( options ){\n    var renderer = this._private.renderer;\n    options = options || {};\n\n    return renderer.png( options );\n  },\n\n  jpg: function( options ){\n    var renderer = this._private.renderer;\n    options = options || {};\n\n    options.bg = options.bg || '#fff';\n\n    return renderer.jpg( options );\n  }\n\n});\n\ncorefn.jpeg = corefn.jpg;\n\nmodule.exports = corefn;\n\n},{}],34:[function(_dereq_,module,exports){\n'use strict';\n\nvar window = _dereq_('../window');\nvar util = _dereq_('../util');\nvar Collection = _dereq_('../collection');\nvar is = _dereq_('../is');\nvar Promise = _dereq_('../promise');\nvar define = _dereq_('../define');\n\nvar Core = function( opts ){\n  if( !(this instanceof Core) ){\n    return new Core(opts);\n  }\n  var cy = this;\n\n  opts = util.extend({}, opts);\n\n  var container = opts.container;\n\n  // allow for passing a wrapped jquery object\n  // e.g. cytoscape({ container: $('#cy') })\n  if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){\n    container = container[0];\n  }\n\n  var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery\n  reg = reg || {};\n\n  if( reg && reg.cy ){\n    reg.cy.destroy();\n\n    reg = {}; // old instance => replace reg completely\n  }\n\n  var readies = reg.readies = reg.readies || [];\n\n  if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy\n  reg.cy = cy;\n\n  var head = window !== undefined && container !== undefined && !opts.headless;\n  var options = opts;\n  options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout );\n  options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer );\n\n  var defVal = function( def, val, altVal ){\n    if( val !== undefined ){\n      return val;\n    } else if( altVal !== undefined ){\n      return altVal;\n    } else {\n      return def;\n    }\n  };\n\n  var _p = this._private = {\n    container: container, // html dom ele container\n    ready: false, // whether ready has been triggered\n    initrender: false, // has initrender has been triggered\n    options: options, // cached options\n    elements: [], // array of elements\n    id2index: {}, // element id => index in elements array\n    listeners: [], // list of listeners\n    onRenders: [], // rendering listeners\n    aniEles: Collection(this), // elements being animated\n    scratch: {}, // scratch object for core\n    layout: null,\n    renderer: null,\n    notificationsEnabled: true, // whether notifications are sent to the renderer\n    minZoom: 1e-50,\n    maxZoom: 1e50,\n    zoomingEnabled: defVal(true, options.zoomingEnabled),\n    userZoomingEnabled: defVal(true, options.userZoomingEnabled),\n    panningEnabled: defVal(true, options.panningEnabled),\n    userPanningEnabled: defVal(true, options.userPanningEnabled),\n    boxSelectionEnabled: defVal(true, options.boxSelectionEnabled),\n    autolock: defVal(false, options.autolock, options.autolockNodes),\n    autoungrabify: defVal(false, options.autoungrabify, options.autoungrabifyNodes),\n    autounselectify: defVal(false, options.autounselectify),\n    styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,\n    zoom: is.number(options.zoom) ? options.zoom : 1,\n    pan: {\n      x: is.plainObject(options.pan) && is.number(options.pan.x) ? options.pan.x : 0,\n      y: is.plainObject(options.pan) && is.number(options.pan.y) ? options.pan.y : 0\n    },\n    animation: { // object for currently-running animations\n      current: [],\n      queue: []\n    },\n    hasCompoundNodes: false,\n    deferredExecQueue: []\n  };\n\n  // set selection type\n  var selType = options.selectionType;\n  if( selType === undefined || (selType !== 'additive' && selType !== 'single') ){\n    // then set default\n\n    _p.selectionType = 'single';\n  } else {\n    _p.selectionType = selType;\n  }\n\n  // init zoom bounds\n  if( is.number(options.minZoom) && is.number(options.maxZoom) && options.minZoom < options.maxZoom ){\n    _p.minZoom = options.minZoom;\n    _p.maxZoom = options.maxZoom;\n  } else if( is.number(options.minZoom) && options.maxZoom === undefined ){\n    _p.minZoom = options.minZoom;\n  } else if( is.number(options.maxZoom) && options.minZoom === undefined ){\n    _p.maxZoom = options.maxZoom;\n  }\n\n  var loadExtData = function( next ){\n    var anyIsPromise = false;\n\n    for( var i = 0; i < extData.length; i++ ){\n      var datum = extData[i];\n\n      if( is.promise(datum) ){\n        anyIsPromise = true;\n        break;\n      }\n    }\n\n    if( anyIsPromise ){\n      return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init\n    } else {\n      next( extData ); // exec synchronously for convenience\n    }\n  };\n\n  // create the renderer\n  cy.initRenderer( util.extend({\n    hideEdgesOnViewport: options.hideEdgesOnViewport,\n    hideLabelsOnViewport: options.hideLabelsOnViewport,\n    textureOnViewport: options.textureOnViewport,\n    wheelSensitivity: is.number(options.wheelSensitivity) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1,\n    motionBlur: options.motionBlur === undefined ? true : options.motionBlur, // on by default\n    motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity,\n    pixelRatio: is.number(options.pixelRatio) && options.pixelRatio > 0 ? options.pixelRatio : undefined,\n    desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold,\n    touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold\n  }, options.renderer) );\n\n  var extData = [ options.style, options.elements ];\n  loadExtData(function( thens ){\n    var initStyle = thens[0];\n    var initEles = thens[1];\n\n    // init style\n    if( _p.styleEnabled ){\n      cy.setStyle( initStyle );\n    }\n\n    // trigger the passed function for the `initrender` event\n    if( options.initrender ){\n      cy.on('initrender', options.initrender);\n      cy.on('initrender', function(){\n        _p.initrender = true;\n      });\n    }\n\n    // initial load\n    cy.load(initEles, function(){ // onready\n      cy.startAnimationLoop();\n      _p.ready = true;\n\n      // if a ready callback is specified as an option, the bind it\n      if( is.fn( options.ready ) ){\n        cy.on('ready', options.ready);\n      }\n\n      // bind all the ready handlers registered before creating this instance\n      for( var i = 0; i < readies.length; i++ ){\n        var fn = readies[i];\n        cy.on('ready', fn);\n      }\n      if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc\n\n      cy.trigger('ready');\n    }, options.done);\n\n  });\n};\n\nvar corefn = Core.prototype; // short alias\n\nutil.extend(corefn, {\n  instanceString: function(){\n    return 'core';\n  },\n\n  isReady: function(){\n    return this._private.ready;\n  },\n\n  ready: function( fn ){\n    if( this.isReady() ){\n      this.trigger('ready', [], fn); // just calls fn as though triggered via ready event\n    } else {\n      this.on('ready', fn);\n    }\n\n    return this;\n  },\n\n  initrender: function(){\n    return this._private.initrender;\n  },\n\n  destroy: function(){\n    var cy = this;\n\n    cy.stopAnimationLoop();\n\n    cy.notify({ type: 'destroy' }); // destroy the renderer\n\n    var domEle = cy.container();\n    if( domEle ){\n      domEle._cyreg = null;\n\n      while( domEle.childNodes.length > 0 ){\n        domEle.removeChild( domEle.childNodes[0] );\n      }\n    }\n\n    return cy;\n  },\n\n  getElementById: function( id ){\n    var index = this._private.id2index[ id ];\n    if( index !== undefined ){\n      return this._private.elements[ index ];\n    }\n\n    // worst case, return an empty collection\n    return Collection( this );\n  },\n\n  selectionType: function(){\n    return this._private.selectionType;\n  },\n\n  hasCompoundNodes: function(){\n    return this._private.hasCompoundNodes;\n  },\n\n  styleEnabled: function(){\n    return this._private.styleEnabled;\n  },\n\n  addToPool: function( eles ){\n    var elements = this._private.elements;\n    var id2index = this._private.id2index;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n\n      var id = ele._private.data.id;\n      var index = id2index[ id ];\n      var alreadyInPool = index !== undefined;\n\n      if( !alreadyInPool ){\n        index = elements.length;\n        elements.push( ele );\n        id2index[ id ] = index;\n        ele._private.index = index;\n      }\n    }\n\n    return this; // chaining\n  },\n\n  removeFromPool: function( eles ){\n    var elements = this._private.elements;\n    var id2index = this._private.id2index;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n\n      var id = ele._private.data.id;\n      var index = id2index[ id ];\n      var inPool = index !== undefined;\n\n      if( inPool ){\n        this._private.id2index[ id ] = undefined;\n        elements.splice(index, 1);\n\n        // adjust the index of all elements past this index\n        for( var j = index; j < elements.length; j++ ){\n          var jid = elements[j]._private.data.id;\n          id2index[ jid ]--;\n          elements[j]._private.index--;\n        }\n      }\n    }\n  },\n\n  container: function(){\n    return this._private.container;\n  },\n\n  options: function(){\n    return util.copy( this._private.options );\n  },\n\n  json: function( obj ){\n    var cy = this;\n    var _p = cy._private;\n\n    if( is.plainObject(obj) ){ // set\n\n      cy.startBatch();\n\n      if( obj.elements ){\n        var idInJson = {};\n\n        var updateEles = function( jsons, gr ){\n          for( var i = 0; i < jsons.length; i++ ){\n            var json = jsons[i];\n            var id = json.data.id;\n            var ele = cy.getElementById( id );\n\n            idInJson[ id ] = true;\n\n            if( ele.length !== 0 ){ // existing element should be updated\n              ele.json( json );\n            } else { // otherwise should be added\n              if( gr ){\n                cy.add( util.extend({ group: gr }, json) );\n              } else {\n                cy.add( json );\n              }\n            }\n          }\n        };\n\n        if( is.array(obj.elements) ){ // elements: []\n          updateEles( obj.elements );\n\n        } else { // elements: { nodes: [], edges: [] }\n          var grs = ['nodes', 'edges'];\n          for( var i = 0; i < grs.length; i++ ){\n            var gr = grs[i];\n            var elements = obj.elements[ gr ];\n\n            if( is.array(elements) ){\n              updateEles( elements, gr );\n            }\n          }\n        }\n\n        // elements not specified in json should be removed\n        cy.elements().stdFilter(function( ele ){\n          return !idInJson[ ele.id() ];\n        }).remove();\n      }\n\n      if( obj.style ){\n        cy.style( obj.style );\n      }\n\n      if( obj.zoom != null && obj.zoom !== _p.zoom ){\n        cy.zoom( obj.zoom );\n      }\n\n      if( obj.pan ){\n        if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){\n          cy.pan( obj.pan );\n        }\n      }\n\n      var fields = [\n        'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled',\n        'panningEnabled', 'userPanningEnabled',\n        'boxSelectionEnabled',\n        'autolock', 'autoungrabify', 'autounselectify'\n      ];\n\n      for( var i = 0; i < fields.length; i++ ){\n        var f = fields[i];\n\n        if( obj[f] != null ){\n          cy[f]( obj[f] );\n        }\n      }\n\n      cy.endBatch();\n\n      return this; // chaining\n    } else if( obj === undefined ){ // get\n      var json = {};\n\n      json.elements = {};\n      cy.elements().each(function(i, ele){\n        var group = ele.group();\n\n        if( !json.elements[group] ){\n          json.elements[group] = [];\n        }\n\n        json.elements[group].push( ele.json() );\n      });\n\n      if( this._private.styleEnabled ){\n        json.style = cy.style().json();\n      }\n\n      json.zoomingEnabled = cy._private.zoomingEnabled;\n      json.userZoomingEnabled = cy._private.userZoomingEnabled;\n      json.zoom = cy._private.zoom;\n      json.minZoom = cy._private.minZoom;\n      json.maxZoom = cy._private.maxZoom;\n      json.panningEnabled = cy._private.panningEnabled;\n      json.userPanningEnabled = cy._private.userPanningEnabled;\n      json.pan = util.copy( cy._private.pan );\n      json.boxSelectionEnabled = cy._private.boxSelectionEnabled;\n      json.renderer = util.copy( cy._private.options.renderer );\n      json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport;\n      json.hideLabelsOnViewport = cy._private.options.hideLabelsOnViewport;\n      json.textureOnViewport = cy._private.options.textureOnViewport;\n      json.wheelSensitivity = cy._private.options.wheelSensitivity;\n      json.motionBlur = cy._private.options.motionBlur;\n\n      return json;\n    }\n  },\n\n  scratch: define.data({\n    field: 'scratch',\n    bindingEvent: 'scratch',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'scratch',\n    settingTriggersEvent: true,\n    triggerFnName: 'trigger',\n    allowGetting: true\n  }),\n\n  removeScratch: define.removeData({\n    field: 'scratch',\n    event: 'scratch',\n    triggerFnName: 'trigger',\n    triggerEvent: true\n  })\n\n});\n\n[\n  _dereq_('./add-remove'),\n  _dereq_('./animation'),\n  _dereq_('./events'),\n  _dereq_('./export'),\n  _dereq_('./layout'),\n  _dereq_('./notification'),\n  _dereq_('./renderer'),\n  _dereq_('./search'),\n  _dereq_('./style'),\n  _dereq_('./viewport')\n].forEach(function( props ){\n  util.extend( corefn, props );\n});\n\nmodule.exports = Core;\n\n},{\"../collection\":23,\"../define\":41,\"../is\":77,\"../promise\":80,\"../util\":94,\"../window\":100,\"./add-remove\":30,\"./animation\":31,\"./events\":32,\"./export\":33,\"./layout\":35,\"./notification\":36,\"./renderer\":37,\"./search\":38,\"./style\":39,\"./viewport\":40}],35:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\nvar corefn = ({\n\n  layout: function( params ){\n    var layout = this._private.prevLayout = ( params == null ? this._private.prevLayout : this.makeLayout( params ) );\n\n    layout.run();\n\n    return this; // chaining\n  },\n\n  makeLayout: function( options ){\n    var cy = this;\n\n    if( options == null ){\n      util.error('Layout options must be specified to make a layout');\n      return;\n    }\n\n    if( options.name == null ){\n      util.error('A `name` must be specified to make a layout');\n      return;\n    }\n\n    var name = options.name;\n    var Layout = cy.extension('layout', name);\n\n    if( Layout == null ){\n      util.error('Can not apply layout: No such layout `' + name + '` found; did you include its JS file?');\n      return;\n    }\n\n    var eles;\n    if( is.string( options.eles ) ){\n      eles = cy.$( options.eles );\n    } else {\n      eles = options.eles != null ? options.eles : cy.$();\n    }\n\n    var layout = new Layout( util.extend({}, options, {\n      cy: cy,\n      eles: eles\n    }) );\n\n    return layout;\n  }\n\n});\n\ncorefn.createLayout = corefn.makeLayout;\n\nmodule.exports = corefn;\n\n},{\"../is\":77,\"../util\":94}],36:[function(_dereq_,module,exports){\n'use strict';\n\nvar corefn = ({\n  notify: function( params ){\n    var _p = this._private;\n\n    if( _p.batchingNotify ){\n      var bEles = _p.batchNotifyEles;\n      var bTypes = _p.batchNotifyTypes;\n\n      if( params.collection ){\n        bEles.merge( params.collection );\n      }\n\n      if( !bTypes.ids[ params.type ] ){\n        bTypes.push( params.type );\n      }\n\n      return; // notifications are disabled during batching\n    }\n\n    if( !_p.notificationsEnabled ){ return; } // exit on disabled\n\n    var renderer = this.renderer();\n\n    renderer.notify(params);\n  },\n\n  notifications: function( bool ){\n    var p = this._private;\n\n    if( bool === undefined ){\n      return p.notificationsEnabled;\n    } else {\n      p.notificationsEnabled = bool ? true : false;\n    }\n  },\n\n  noNotifications: function( callback ){\n    this.notifications(false);\n    callback();\n    this.notifications(true);\n  },\n\n  startBatch: function(){\n    var _p = this._private;\n\n    if( _p.batchCount == null ){\n      _p.batchCount = 0;\n    }\n\n    if( _p.batchCount === 0 ){\n      _p.batchingStyle = _p.batchingNotify = true;\n      _p.batchStyleEles = this.collection();\n      _p.batchNotifyEles = this.collection();\n      _p.batchNotifyTypes = [];\n\n      _p.batchNotifyTypes.ids = {};\n    }\n\n    _p.batchCount++;\n\n    return this;\n  },\n\n  endBatch: function(){\n    var _p = this._private;\n\n    _p.batchCount--;\n\n    if( _p.batchCount === 0 ){\n      // update style for dirty eles\n      _p.batchingStyle = false;\n      _p.batchStyleEles.updateStyle();\n\n      // notify the renderer of queued eles and event types\n      _p.batchingNotify = false;\n      this.notify({\n        type: _p.batchNotifyTypes,\n        collection: _p.batchNotifyEles\n      });\n    }\n\n    return this;\n  },\n\n  batch: function( callback ){\n    this.startBatch();\n    callback();\n    this.endBatch();\n\n    return this;\n  },\n\n  // for backwards compatibility\n  batchData: function( map ){\n    var cy = this;\n\n    return this.batch(function(){\n      for( var id in map ){\n        var data = map[id];\n        var ele = cy.getElementById( id );\n\n        ele.data( data );\n      }\n    });\n  }\n});\n\nmodule.exports = corefn;\n\n},{}],37:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\n\nvar corefn = ({\n\n  renderTo: function( context, zoom, pan, pxRatio ){\n    var r = this._private.renderer;\n\n    r.renderTo( context, zoom, pan, pxRatio );\n    return this;\n  },\n\n  renderer: function(){\n    return this._private.renderer;\n  },\n\n  forceRender: function(){\n    this.notify({\n      type: 'draw'\n    });\n\n    return this;\n  },\n\n  resize: function(){\n    this.notify({\n      type: 'resize'\n    });\n\n    this.trigger('resize');\n\n    return this;\n  },\n\n  initRenderer: function( options ){\n    var cy = this;\n\n    var RendererProto = cy.extension('renderer', options.name);\n    if( RendererProto == null ){\n      util.error('Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name);\n      return;\n    }\n\n    var rOpts = util.extend({}, options, {\n      cy: cy\n    });\n    var renderer = cy._private.renderer = new RendererProto( rOpts );\n\n    renderer.init( rOpts );\n\n  },\n\n  triggerOnRender: function(){\n    var cbs = this._private.onRenders;\n\n    for( var i = 0; i < cbs.length; i++ ){\n      var cb = cbs[i];\n\n      cb();\n    }\n\n    return this;\n  },\n\n  onRender: function( cb ){\n    this._private.onRenders.push( cb );\n\n    return this;\n  },\n\n  offRender: function( fn ){\n    var cbs = this._private.onRenders;\n\n    if( fn == null ){ // unbind all\n      this._private.onRenders = [];\n      return this;\n    }\n\n    for( var i = 0; i < cbs.length; i++ ){ // unbind specified\n      var cb = cbs[i];\n\n      if( fn === cb ){\n        cbs.splice( i, 1 );\n        break;\n      }\n    }\n\n    return this;\n  }\n\n});\n\ncorefn.invalidateDimensions = corefn.resize;\n\nmodule.exports = corefn;\n\n},{\"../util\":94}],38:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar Collection = _dereq_('../collection');\n\nvar corefn = ({\n\n  // get a collection\n  // - empty collection on no args\n  // - collection of elements in the graph on selector arg\n  // - guarantee a returned collection when elements or collection specified\n  collection: function( eles, opts ){\n\n    if( is.string( eles ) ){\n      return this.$( eles );\n\n    } else if( is.elementOrCollection( eles ) ){\n      return eles.collection();\n\n    } else if( is.array( eles ) ){\n      return Collection( this, eles, opts );\n    }\n\n    return Collection( this );\n  },\n\n  nodes: function( selector ){\n    var nodes = this.$(function(){\n      return this.isNode();\n    });\n\n    if( selector ){\n      return nodes.filter( selector );\n    }\n\n    return nodes;\n  },\n\n  edges: function( selector ){\n    var edges = this.$(function(){\n      return this.isEdge();\n    });\n\n    if( selector ){\n      return edges.filter( selector );\n    }\n\n    return edges;\n  },\n\n  // search the graph like jQuery\n  $: function( selector ){\n    var eles = new Collection( this, this._private.elements );\n\n    if( selector ){\n      return eles.filter( selector );\n    }\n\n    return eles;\n  }\n\n});\n\n// aliases\ncorefn.elements = corefn.filter = corefn.$;\n\nmodule.exports = corefn;\n\n},{\"../collection\":23,\"../is\":77}],39:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar Style = _dereq_('../style');\n\nvar corefn = ({\n\n  style: function( newStyle ){\n    if( newStyle ){\n      var s = this.setStyle( newStyle );\n\n      s.update();\n    }\n\n    return this._private.style;\n  },\n\n  setStyle: function( style ){\n    var _p = this._private;\n\n    if( is.stylesheet(style) ){\n      _p.style = style.generateStyle(this);\n\n    } else if( is.array(style) ) {\n      _p.style = Style.fromJson(this, style);\n\n    } else if( is.string(style) ){\n      _p.style = Style.fromString(this, style);\n\n    } else {\n      _p.style = Style( this );\n    }\n\n    return _p.style;\n  }\n});\n\nmodule.exports = corefn;\n\n},{\"../is\":77,\"../style\":86}],40:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\n\nvar corefn = ({\n\n  autolock: function(bool){\n    if( bool !== undefined ){\n      this._private.autolock = bool ? true : false;\n    } else {\n      return this._private.autolock;\n    }\n\n    return this; // chaining\n  },\n\n  autoungrabify: function(bool){\n    if( bool !== undefined ){\n      this._private.autoungrabify = bool ? true : false;\n    } else {\n      return this._private.autoungrabify;\n    }\n\n    return this; // chaining\n  },\n\n  autounselectify: function(bool){\n    if( bool !== undefined ){\n      this._private.autounselectify = bool ? true : false;\n    } else {\n      return this._private.autounselectify;\n    }\n\n    return this; // chaining\n  },\n\n  panningEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.panningEnabled = bool ? true : false;\n    } else {\n      return this._private.panningEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  userPanningEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.userPanningEnabled = bool ? true : false;\n    } else {\n      return this._private.userPanningEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  zoomingEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.zoomingEnabled = bool ? true : false;\n    } else {\n      return this._private.zoomingEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  userZoomingEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.userZoomingEnabled = bool ? true : false;\n    } else {\n      return this._private.userZoomingEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  boxSelectionEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.boxSelectionEnabled = bool ? true : false;\n    } else {\n      return this._private.boxSelectionEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  pan: function(){\n    var args = arguments;\n    var pan = this._private.pan;\n    var dim, val, dims, x, y;\n\n    switch( args.length ){\n    case 0: // .pan()\n      return pan;\n\n    case 1:\n\n      if( is.string( args[0] ) ){ // .pan('x')\n        dim = args[0];\n        return pan[ dim ];\n\n      } else if( is.plainObject( args[0] ) ) { // .pan({ x: 0, y: 100 })\n        if( !this._private.panningEnabled ){\n          return this;\n        }\n\n        dims = args[0];\n        x = dims.x;\n        y = dims.y;\n\n        if( is.number(x) ){\n          pan.x = x;\n        }\n\n        if( is.number(y) ){\n          pan.y = y;\n        }\n\n        this.trigger('pan viewport');\n      }\n      break;\n\n    case 2: // .pan('x', 100)\n      if( !this._private.panningEnabled ){\n        return this;\n      }\n\n      dim = args[0];\n      val = args[1];\n\n      if( (dim === 'x' || dim === 'y') && is.number(val) ){\n        pan[dim] = val;\n      }\n\n      this.trigger('pan viewport');\n      break;\n\n    default:\n      break; // invalid\n    }\n\n    this.notify({ // notify the renderer that the viewport changed\n      type: 'viewport'\n    });\n\n    return this; // chaining\n  },\n\n  panBy: function(params){\n    var args = arguments;\n    var pan = this._private.pan;\n    var dim, val, dims, x, y;\n\n    if( !this._private.panningEnabled ){\n      return this;\n    }\n\n    switch( args.length ){\n    case 1:\n\n      if( is.plainObject( args[0] ) ) { // .panBy({ x: 0, y: 100 })\n        dims = args[0];\n        x = dims.x;\n        y = dims.y;\n\n        if( is.number(x) ){\n          pan.x += x;\n        }\n\n        if( is.number(y) ){\n          pan.y += y;\n        }\n\n        this.trigger('pan viewport');\n      }\n      break;\n\n    case 2: // .panBy('x', 100)\n      dim = args[0];\n      val = args[1];\n\n      if( (dim === 'x' || dim === 'y') && is.number(val) ){\n        pan[dim] += val;\n      }\n\n      this.trigger('pan viewport');\n      break;\n\n    default:\n      break; // invalid\n    }\n\n    this.notify({ // notify the renderer that the viewport changed\n      type: 'viewport'\n    });\n\n    return this; // chaining\n  },\n\n  fit: function( elements, padding ){\n    var viewportState = this.getFitViewport( elements, padding );\n\n    if( viewportState ){\n      var _p = this._private;\n      _p.zoom = viewportState.zoom;\n      _p.pan = viewportState.pan;\n\n      this.trigger('pan zoom viewport');\n\n      this.notify({ // notify the renderer that the viewport changed\n        type: 'viewport'\n      });\n    }\n\n    return this; // chaining\n  },\n\n  getFitViewport: function( elements, padding ){\n    if( is.number(elements) && padding === undefined ){ // elements is optional\n      padding = elements;\n      elements = undefined;\n    }\n\n    if( !this._private.panningEnabled || !this._private.zoomingEnabled ){\n      return;\n    }\n\n    var bb;\n\n    if( is.string(elements) ){\n      var sel = elements;\n      elements = this.$( sel );\n\n    } else if( is.boundingBox(elements) ){ // assume bb\n      var bbe = elements;\n      bb = {\n        x1: bbe.x1,\n        y1: bbe.y1,\n        x2: bbe.x2,\n        y2: bbe.y2\n      };\n\n      bb.w = bb.x2 - bb.x1;\n      bb.h = bb.y2 - bb.y1;\n\n    } else if( !is.elementOrCollection(elements) ){\n      elements = this.elements();\n    }\n\n    bb = bb || elements.boundingBox();\n\n    var w = this.width();\n    var h = this.height();\n    var zoom;\n    padding = is.number(padding) ? padding : 0;\n\n    if( !isNaN(w) && !isNaN(h) && w > 0 && h > 0 && !isNaN(bb.w) && !isNaN(bb.h) &&  bb.w > 0 && bb.h > 0 ){\n      zoom = Math.min( (w - 2*padding)/bb.w, (h - 2*padding)/bb.h );\n\n      // crop zoom\n      zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;\n      zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;\n\n      var pan = { // now pan to middle\n        x: (w - zoom*( bb.x1 + bb.x2 ))/2,\n        y: (h - zoom*( bb.y1 + bb.y2 ))/2\n      };\n\n      return {\n        zoom: zoom,\n        pan: pan\n      };\n    }\n\n    return;\n  },\n\n  minZoom: function( zoom ){\n    if( zoom === undefined ){\n      return this._private.minZoom;\n    } else if( is.number(zoom) ){\n      this._private.minZoom = zoom;\n    }\n\n    return this;\n  },\n\n  maxZoom: function( zoom ){\n    if( zoom === undefined ){\n      return this._private.maxZoom;\n    } else if( is.number(zoom) ){\n      this._private.maxZoom = zoom;\n    }\n\n    return this;\n  },\n\n  zoom: function( params ){\n    var pos; // in rendered px\n    var zoom;\n\n    if( params === undefined ){ // then get the zoom\n      return this._private.zoom;\n\n    } else if( is.number(params) ){ // then set the zoom\n      zoom = params;\n\n    } else if( is.plainObject(params) ){ // then zoom about a point\n      zoom = params.level;\n\n      if( params.position ){\n        var p = params.position;\n        var pan = this._private.pan;\n        var z = this._private.zoom;\n\n        pos = { // convert to rendered px\n          x: p.x * z + pan.x,\n          y: p.y * z + pan.y\n        };\n      } else if( params.renderedPosition ){\n        pos = params.renderedPosition;\n      }\n\n      if( pos && !this._private.panningEnabled ){\n        return this; // panning disabled\n      }\n    }\n\n    if( !this._private.zoomingEnabled ){\n      return this; // zooming disabled\n    }\n\n    if( !is.number(zoom) || ( pos && (!is.number(pos.x) || !is.number(pos.y)) ) ){\n      return this; // can't zoom with invalid params\n    }\n\n    // crop zoom\n    zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;\n    zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;\n\n    if( pos ){ // set zoom about position\n      var pan1 = this._private.pan;\n      var zoom1 = this._private.zoom;\n      var zoom2 = zoom;\n\n      var pan2 = {\n        x: -zoom2/zoom1 * (pos.x - pan1.x) + pos.x,\n        y: -zoom2/zoom1 * (pos.y - pan1.y) + pos.y\n      };\n\n      this._private.zoom = zoom;\n      this._private.pan = pan2;\n\n      var posChanged = pan1.x !== pan2.x || pan1.y !== pan2.y;\n      this.trigger(' zoom ' + (posChanged ? ' pan ' : '') + ' viewport ' );\n\n    } else { // just set the zoom\n      this._private.zoom = zoom;\n      this.trigger('zoom viewport');\n    }\n\n    this.notify({ // notify the renderer that the viewport changed\n      type: 'viewport'\n    });\n\n    return this; // chaining\n  },\n\n  viewport: function( opts ){\n    var _p = this._private;\n    var zoomDefd = true;\n    var panDefd = true;\n    var events = []; // to trigger\n    var zoomFailed = false;\n    var panFailed = false;\n\n    if( !opts ){ return this; }\n    if( !is.number(opts.zoom) ){ zoomDefd = false; }\n    if( !is.plainObject(opts.pan) ){ panDefd = false; }\n    if( !zoomDefd && !panDefd ){ return this; }\n\n    if( zoomDefd ){\n      var z = opts.zoom;\n\n      if( z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled ){\n        zoomFailed = true;\n\n      } else {\n        _p.zoom = z;\n\n        events.push('zoom');\n      }\n    }\n\n    if( panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled ){\n      var p = opts.pan;\n\n      if( is.number(p.x) ){\n        _p.pan.x = p.x;\n        panFailed = false;\n      }\n\n      if( is.number(p.y) ){\n        _p.pan.y = p.y;\n        panFailed = false;\n      }\n\n      if( !panFailed ){\n        events.push('pan');\n      }\n    }\n\n    if( events.length > 0 ){\n      events.push('viewport');\n      this.trigger( events.join(' ') );\n\n      this.notify({\n        type: 'viewport'\n      });\n    }\n\n    return this; // chaining\n  },\n\n  center: function( elements ){\n    var pan = this.getCenterPan( elements );\n\n    if( pan ){\n      this._private.pan = pan;\n\n      this.trigger('pan viewport');\n\n      this.notify({ // notify the renderer that the viewport changed\n        type: 'viewport'\n      });\n    }\n\n    return this; // chaining\n  },\n\n  getCenterPan: function( elements, zoom ){\n    if( !this._private.panningEnabled ){\n      return;\n    }\n\n    if( is.string(elements) ){\n      var selector = elements;\n      elements = this.elements( selector );\n    } else if( !is.elementOrCollection(elements) ){\n      elements = this.elements();\n    }\n\n    var bb = elements.boundingBox();\n    var w = this.width();\n    var h = this.height();\n    zoom = zoom === undefined ? this._private.zoom : zoom;\n\n    var pan = { // middle\n      x: (w - zoom*( bb.x1 + bb.x2 ))/2,\n      y: (h - zoom*( bb.y1 + bb.y2 ))/2\n    };\n\n    return pan;\n  },\n\n  reset: function(){\n    if( !this._private.panningEnabled || !this._private.zoomingEnabled ){\n      return this;\n    }\n\n    this.viewport({\n      pan: { x: 0, y: 0 },\n      zoom: 1\n    });\n\n    return this; // chaining\n  },\n\n  width: function(){\n    var container = this._private.container;\n\n    if( container ){\n      return container.clientWidth;\n    }\n\n    return 1; // fallback if no container (not 0 b/c can be used for dividing etc)\n  },\n\n  height: function(){\n    var container = this._private.container;\n\n    if( container ){\n      return container.clientHeight;\n    }\n\n    return 1; // fallback if no container (not 0 b/c can be used for dividing etc)\n  },\n\n  extent: function(){\n    var pan = this._private.pan;\n    var zoom = this._private.zoom;\n    var rb = this.renderedExtent();\n\n    var b = {\n      x1: ( rb.x1 - pan.x )/zoom,\n      x2: ( rb.x2 - pan.x )/zoom,\n      y1: ( rb.y1 - pan.y )/zoom,\n      y2: ( rb.y2 - pan.y )/zoom\n    };\n\n    b.w = b.x2 - b.x1;\n    b.h = b.y2 - b.y1;\n\n    return b;\n  },\n\n  renderedExtent: function(){\n    var width = this.width();\n    var height = this.height();\n\n    return {\n      x1: 0,\n      y1: 0,\n      x2: width,\n      y2: height,\n      w: width,\n      h: height\n    };\n  }\n});\n\n// aliases\ncorefn.centre = corefn.center;\n\n// backwards compatibility\ncorefn.autolockNodes = corefn.autolock;\ncorefn.autoungrabifyNodes = corefn.autoungrabify;\n\nmodule.exports = corefn;\n\n},{\"../is\":77}],41:[function(_dereq_,module,exports){\n'use strict';\n\n// use this module to cherry pick functions into your prototype\n// (useful for functions shared between the core and collections, for example)\n\n// e.g.\n// var foo = define.foo({ /* params... */ })\n\nvar util = _dereq_('./util');\nvar is = _dereq_('./is');\nvar Selector = _dereq_('./selector');\nvar Promise = _dereq_('./promise');\nvar Event = _dereq_('./event');\nvar Animation = _dereq_('./animation');\n\nvar define = {\n\n  // access data field\n  data: function( params ){\n    var defaults = {\n      field: 'data',\n      bindingEvent: 'data',\n      allowBinding: false,\n      allowSetting: false,\n      allowGetting: false,\n      settingEvent: 'data',\n      settingTriggersEvent: false,\n      triggerFnName: 'trigger',\n      immutableKeys: {}, // key => true if immutable\n      updateStyle: false,\n      onSet: function( self ){},\n      canSet: function( self ){ return true; }\n    };\n    params = util.extend({}, defaults, params);\n\n    return function dataImpl( name, value ){\n      var p = params;\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var single = selfIsArrayLike ? self[0] : self;\n\n      // .data('foo', ...)\n      if( is.string(name) ){ // set or get property\n\n        // .data('foo')\n        if( p.allowGetting && value === undefined ){ // get\n\n          var ret;\n          if( single ){\n            ret = single._private[ p.field ][ name ];\n          }\n          return ret;\n\n        // .data('foo', 'bar')\n        } else if( p.allowSetting && value !== undefined ) { // set\n          var valid = !p.immutableKeys[name];\n          if( valid ){\n            for( var i = 0, l = all.length; i < l; i++ ){\n              if( p.canSet( all[i] ) ){\n                all[i]._private[ p.field ][ name ] = value;\n              }\n            }\n\n            // update mappers if asked\n            if( p.updateStyle ){ self.updateStyle(); }\n\n            // call onSet callback\n            p.onSet( self );\n\n            if( p.settingTriggersEvent ){\n              self[ p.triggerFnName ]( p.settingEvent );\n            }\n          }\n        }\n\n      // .data({ 'foo': 'bar' })\n      } else if( p.allowSetting && is.plainObject(name) ){ // extend\n        var obj = name;\n        var k, v;\n\n        for( k in obj ){\n          v = obj[ k ];\n\n          var valid = !p.immutableKeys[k];\n          if( valid ){\n            for( var i = 0, l = all.length; i < l; i++ ){\n              if( p.canSet( all[i] ) ){\n                all[i]._private[ p.field ][ k ] = v;\n              }\n            }\n          }\n        }\n\n        // update mappers if asked\n        if( p.updateStyle ){ self.updateStyle(); }\n\n        // call onSet callback\n        p.onSet( self );\n\n        if( p.settingTriggersEvent ){\n          self[ p.triggerFnName ]( p.settingEvent );\n        }\n\n      // .data(function(){ ... })\n      } else if( p.allowBinding && is.fn(name) ){ // bind to event\n        var fn = name;\n        self.bind( p.bindingEvent, fn );\n\n      // .data()\n      } else if( p.allowGetting && name === undefined ){ // get whole object\n        var ret;\n        if( single ){\n          ret = single._private[ p.field ];\n        }\n        return ret;\n      }\n\n      return self; // maintain chainability\n    }; // function\n  }, // data\n\n  // remove data field\n  removeData: function( params ){\n    var defaults = {\n      field: 'data',\n      event: 'data',\n      triggerFnName: 'trigger',\n      triggerEvent: false,\n      immutableKeys: {} // key => true if immutable\n    };\n    params = util.extend({}, defaults, params);\n\n    return function removeDataImpl( names ){\n      var p = params;\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n      // .removeData('foo bar')\n      if( is.string(names) ){ // then get the list of keys, and delete them\n        var keys = names.split(/\\s+/);\n        var l = keys.length;\n\n        for( var i = 0; i < l; i++ ){ // delete each non-empty key\n          var key = keys[i];\n          if( is.emptyString(key) ){ continue; }\n\n          var valid = !p.immutableKeys[ key ]; // not valid if immutable\n          if( valid ){\n            for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){\n              all[ i_a ]._private[ p.field ][ key ] = undefined;\n            }\n          }\n        }\n\n        if( p.triggerEvent ){\n          self[ p.triggerFnName ]( p.event );\n        }\n\n      // .removeData()\n      } else if( names === undefined ){ // then delete all keys\n\n        for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){\n          var _privateFields = all[ i_a ]._private[ p.field ];\n\n          for( var key in _privateFields ){\n            var validKeyToDelete = !p.immutableKeys[ key ];\n\n            if( validKeyToDelete ){\n              _privateFields[ key ] = undefined;\n            }\n          }\n        }\n\n        if( p.triggerEvent ){\n          self[ p.triggerFnName ]( p.event );\n        }\n      }\n\n      return self; // maintain chaining\n    }; // function\n  }, // removeData\n\n  // event function reusable stuff\n  event: {\n    regex: /(\\w+)(\\.\\w+)?/, // regex for matching event strings (e.g. \"click.namespace\")\n    optionalTypeRegex: /(\\w+)?(\\.\\w+)?/,\n    falseCallback: function(){ return false; }\n  },\n\n  // event binding\n  on: function( params ){\n    var defaults = {\n      unbindSelfOnTrigger: false,\n      unbindAllBindersOnTrigger: false\n    };\n    params = util.extend({}, defaults, params);\n\n    return function onImpl(events, selector, data, callback){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var eventsIsString = is.string(events);\n      var p = params;\n\n      if( is.plainObject(selector) ){ // selector is actually data\n        callback = data;\n        data = selector;\n        selector = undefined;\n      } else if( is.fn(selector) || selector === false ){ // selector is actually callback\n        callback = selector;\n        data = undefined;\n        selector = undefined;\n      }\n\n      if( is.fn(data) || data === false ){ // data is actually callback\n        callback = data;\n        data = undefined;\n      }\n\n      // if there isn't a callback, we can't really do anything\n      // (can't speak for mapped events arg version)\n      if( !(is.fn(callback) || callback === false) && eventsIsString ){\n        return self; // maintain chaining\n      }\n\n      if( eventsIsString ){ // then convert to map\n        var map = {};\n        map[ events ] = callback;\n        events = map;\n      }\n\n      for( var evts in events ){\n        callback = events[evts];\n        if( callback === false ){\n          callback = define.event.falseCallback;\n        }\n\n        if( !is.fn(callback) ){ continue; }\n\n        evts = evts.split(/\\s+/);\n        for( var i = 0; i < evts.length; i++ ){\n          var evt = evts[i];\n          if( is.emptyString(evt) ){ continue; }\n\n          var match = evt.match( define.event.regex ); // type[.namespace]\n\n          if( match ){\n            var type = match[1];\n            var namespace = match[2] ? match[2] : undefined;\n\n            var listener = {\n              callback: callback, // callback to run\n              data: data, // extra data in eventObj.data\n              delegated: selector ? true : false, // whether the evt is delegated\n              selector: selector, // the selector to match for delegated events\n              selObj: new Selector(selector), // cached selector object to save rebuilding\n              type: type, // the event type (e.g. 'click')\n              namespace: namespace, // the event namespace (e.g. \".foo\")\n              unbindSelfOnTrigger: p.unbindSelfOnTrigger,\n              unbindAllBindersOnTrigger: p.unbindAllBindersOnTrigger,\n              binders: all // who bound together\n            };\n\n            for( var j = 0; j < all.length; j++ ){\n              var _p = all[j]._private;\n\n              _p.listeners = _p.listeners || [];\n              _p.listeners.push( listener );\n            }\n          }\n        } // for events array\n      } // for events map\n\n      return self; // maintain chaining\n    }; // function\n  }, // on\n\n  eventAliasesOn: function( proto ){\n    var p = proto;\n\n    p.addListener = p.listen = p.bind = p.on;\n    p.removeListener = p.unlisten = p.unbind = p.off;\n    p.emit = p.trigger;\n\n    // this is just a wrapper alias of .on()\n    p.pon = p.promiseOn = function( events, selector ){\n      var self = this;\n      var args = Array.prototype.slice.call( arguments, 0 );\n\n      return new Promise(function( resolve, reject ){\n        var callback = function( e ){\n          self.off.apply( self, offArgs );\n\n          resolve( e );\n        };\n\n        var onArgs = args.concat([ callback ]);\n        var offArgs = onArgs.concat([]);\n\n        self.on.apply( self, onArgs );\n      });\n    };\n  },\n\n  off: function offImpl( params ){\n    var defaults = {\n    };\n    params = util.extend({}, defaults, params);\n\n    return function(events, selector, callback){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var eventsIsString = is.string(events);\n\n      if( arguments.length === 0 ){ // then unbind all\n\n        for( var i = 0; i < all.length; i++ ){\n          all[i]._private.listeners = [];\n        }\n\n        return self; // maintain chaining\n      }\n\n      if( is.fn(selector) || selector === false ){ // selector is actually callback\n        callback = selector;\n        selector = undefined;\n      }\n\n      if( eventsIsString ){ // then convert to map\n        var map = {};\n        map[ events ] = callback;\n        events = map;\n      }\n\n      for( var evts in events ){\n        callback = events[evts];\n\n        if( callback === false ){\n          callback = define.event.falseCallback;\n        }\n\n        evts = evts.split(/\\s+/);\n        for( var h = 0; h < evts.length; h++ ){\n          var evt = evts[h];\n          if( is.emptyString(evt) ){ continue; }\n\n          var match = evt.match( define.event.optionalTypeRegex ); // [type][.namespace]\n          if( match ){\n            var type = match[1] ? match[1] : undefined;\n            var namespace = match[2] ? match[2] : undefined;\n\n            for( var i = 0; i < all.length; i++ ){ //\n              var listeners = all[i]._private.listeners = all[i]._private.listeners || [];\n\n              for( var j = 0; j < listeners.length; j++ ){\n                var listener = listeners[j];\n                var nsMatches = !namespace || namespace === listener.namespace;\n                var typeMatches = !type || listener.type === type;\n                var cbMatches = !callback || callback === listener.callback;\n                var listenerMatches = nsMatches && typeMatches && cbMatches;\n\n                // delete listener if it matches\n                if( listenerMatches ){\n                  listeners.splice(j, 1);\n                  j--;\n                }\n              } // for listeners\n            } // for all\n          } // if match\n        } // for events array\n\n      } // for events map\n\n      return self; // maintain chaining\n    }; // function\n  }, // off\n\n  trigger: function( params ){\n    var defaults = {};\n    params = util.extend({}, defaults, params);\n\n    return function triggerImpl(events, extraParams, fnToTrigger){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var eventsIsString = is.string(events);\n      var eventsIsObject = is.plainObject(events);\n      var eventsIsEvent = is.event(events);\n      var cy = this._private.cy || ( is.core(this) ? this : null );\n      var hasCompounds = cy ? cy.hasCompoundNodes() : false;\n\n      if( eventsIsString ){ // then make a plain event object for each event name\n        var evts = events.split(/\\s+/);\n        events = [];\n\n        for( var i = 0; i < evts.length; i++ ){\n          var evt = evts[i];\n          if( is.emptyString(evt) ){ continue; }\n\n          var match = evt.match( define.event.regex ); // type[.namespace]\n          var type = match[1];\n          var namespace = match[2] ? match[2] : undefined;\n\n          events.push( {\n            type: type,\n            namespace: namespace\n          } );\n        }\n      } else if( eventsIsObject ){ // put in length 1 array\n        var eventArgObj = events;\n\n        events = [ eventArgObj ];\n      }\n\n      if( extraParams ){\n        if( !is.array(extraParams) ){ // make sure extra params are in an array if specified\n          extraParams = [ extraParams ];\n        }\n      } else { // otherwise, we've got nothing\n        extraParams = [];\n      }\n\n      for( var i = 0; i < events.length; i++ ){ // trigger each event in order\n        var evtObj = events[i];\n\n        for( var j = 0; j < all.length; j++ ){ // for each\n          var triggerer = all[j];\n          var listeners = triggerer._private.listeners = triggerer._private.listeners || [];\n          var triggererIsElement = is.element(triggerer);\n          var bubbleUp = triggererIsElement || params.layout;\n\n          // create the event for this element from the event object\n          var evt;\n\n          if( eventsIsEvent ){ // then just get the object\n            evt = evtObj;\n\n            evt.cyTarget = evt.cyTarget || triggerer;\n            evt.cy = evt.cy || cy;\n\n          } else { // then we have to make one\n            evt = new Event( evtObj, {\n              cyTarget: triggerer,\n              cy: cy,\n              namespace: evtObj.namespace\n            } );\n          }\n\n          // if a layout was specified, then put it in the typed event\n          if( evtObj.layout ){\n            evt.layout = evtObj.layout;\n          }\n\n          // if triggered by layout, put in event\n          if( params.layout ){\n            evt.layout = triggerer;\n          }\n\n          // create a rendered position based on the passed position\n          if( evt.cyPosition ){\n            var pos = evt.cyPosition;\n            var zoom = cy.zoom();\n            var pan = cy.pan();\n\n            evt.cyRenderedPosition = {\n              x: pos.x * zoom + pan.x,\n              y: pos.y * zoom + pan.y\n            };\n          }\n\n          if( fnToTrigger ){ // then override the listeners list with just the one we specified\n            listeners = [{\n              namespace: evt.namespace,\n              type: evt.type,\n              callback: fnToTrigger\n            }];\n          }\n\n          for( var k = 0; k < listeners.length; k++ ){ // check each listener\n            var lis = listeners[k];\n            var nsMatches = !lis.namespace || lis.namespace === evt.namespace;\n            var typeMatches = lis.type === evt.type;\n            var targetMatches = lis.delegated ? ( triggerer !== evt.cyTarget && is.element(evt.cyTarget) && lis.selObj.matches(evt.cyTarget) ) : (true); // we're not going to validate the hierarchy; that's too expensive\n            var listenerMatches = nsMatches && typeMatches && targetMatches;\n\n            if( listenerMatches ){ // then trigger it\n              var args = [ evt ];\n              args = args.concat( extraParams ); // add extra params to args list\n\n              if( lis.data ){ // add on data plugged into binding\n                evt.data = lis.data;\n              } else { // or clear it in case the event obj is reused\n                evt.data = undefined;\n              }\n\n              if( lis.unbindSelfOnTrigger || lis.unbindAllBindersOnTrigger ){ // then remove listener\n                listeners.splice(k, 1);\n                k--;\n              }\n\n              if( lis.unbindAllBindersOnTrigger ){ // then delete the listener for all binders\n                var binders = lis.binders;\n                for( var l = 0; l < binders.length; l++ ){\n                  var binder = binders[l];\n                  if( !binder || binder === triggerer ){ continue; } // already handled triggerer or we can't handle it\n\n                  var binderListeners = binder._private.listeners;\n                  for( var m = 0; m < binderListeners.length; m++ ){\n                    var binderListener = binderListeners[m];\n\n                    if( binderListener === lis ){ // delete listener from list\n                      binderListeners.splice(m, 1);\n                      m--;\n                    }\n                  }\n                }\n              }\n\n              // run the callback\n              var context = lis.delegated ? evt.cyTarget : triggerer;\n              var ret = lis.callback.apply( context, args );\n\n              if( ret === false || evt.isPropagationStopped() ){\n                // then don't bubble\n                bubbleUp = false;\n\n                if( ret === false ){\n                  // returning false is a shorthand for stopping propagation and preventing the def. action\n                  evt.stopPropagation();\n                  evt.preventDefault();\n                }\n              }\n            } // if listener matches\n          } // for each listener\n\n          // bubble up event for elements\n          if( bubbleUp ){\n            var parent = hasCompounds ? triggerer._private.parent : null;\n            var hasParent = parent != null && parent.length !== 0;\n\n            if( hasParent ){ // then bubble up to parent\n              parent = parent[0];\n              parent.trigger(evt);\n            } else { // otherwise, bubble up to the core\n              cy.trigger(evt);\n            }\n          }\n\n        } // for each of all\n      } // for each event\n\n      return self; // maintain chaining\n    }; // function\n  }, // trigger\n\n  animated: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function animatedImpl(){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return false; }\n\n      var ele = all[0];\n\n      if( ele ){\n        return ele._private.animation.current.length > 0;\n      }\n    };\n  }, // animated\n\n  clearQueue: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function clearQueueImpl(){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      for( var i = 0; i < all.length; i++ ){\n        var ele = all[i];\n        ele._private.animation.queue = [];\n      }\n\n      return this;\n    };\n  }, // clearQueue\n\n  delay: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function delayImpl( time, complete ){\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      return this.animate({\n        delay: time,\n        duration: time,\n        complete: complete\n      });\n    };\n  }, // delay\n\n  delayAnimation: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function delayAnimationImpl( time, complete ){\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      return this.animation({\n        delay: time,\n        duration: time,\n        complete: complete\n      });\n    };\n  }, // delay\n\n  animation: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function animationImpl( properties, params ){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n      var isCore = !selfIsArrayLike;\n      var isEles = !isCore;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      var style = cy.style();\n\n      properties = util.extend( {}, properties, params );\n\n      if( properties.duration === undefined ){\n        properties.duration = 400;\n      }\n\n      switch( properties.duration ){\n      case 'slow':\n        properties.duration = 600;\n        break;\n      case 'fast':\n        properties.duration = 200;\n        break;\n      }\n\n      var propertiesEmpty = true;\n      if( properties ){ for( var i in properties ){ // jshint ignore:line\n        propertiesEmpty = false;\n        break;\n      } }\n\n      if( propertiesEmpty ){\n        return new Animation( all[0], properties ); // nothing to animate\n      }\n\n      if( isEles ){\n        properties.style = style.getPropsList( properties.style || properties.css );\n\n        properties.css = undefined;\n      }\n\n      if( properties.renderedPosition && isEles ){\n        var rpos = properties.renderedPosition;\n        var pan = cy.pan();\n        var zoom = cy.zoom();\n\n        properties.position = {\n          x: ( rpos.x - pan.x ) /zoom,\n          y: ( rpos.y - pan.y ) /zoom\n        };\n      }\n\n      // override pan w/ panBy if set\n      if( properties.panBy && isCore ){\n        var panBy = properties.panBy;\n        var cyPan = cy.pan();\n\n        properties.pan = {\n          x: cyPan.x + panBy.x,\n          y: cyPan.y + panBy.y\n        };\n      }\n\n      // override pan w/ center if set\n      var center = properties.center || properties.centre;\n      if( center && isCore ){\n        var centerPan = cy.getCenterPan( center.eles, properties.zoom );\n\n        if( centerPan ){\n          properties.pan = centerPan;\n        }\n      }\n\n      // override pan & zoom w/ fit if set\n      if( properties.fit && isCore ){\n        var fit = properties.fit;\n        var fitVp = cy.getFitViewport( fit.eles || fit.boundingBox, fit.padding );\n\n        if( fitVp ){\n          properties.pan = fitVp.pan;\n          properties.zoom = fitVp.zoom;\n        }\n      }\n\n      return new Animation( all[0], properties );\n    };\n  }, // animate\n\n  animate: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function animateImpl( properties, params ){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      if( params ){\n        properties = util.extend( {}, properties, params );\n      }\n\n      // manually hook and run the animation\n      for( var i = 0; i < all.length; i++ ){\n        var ele = all[i];\n        var queue = ele.animated() && (properties.queue === undefined || properties.queue);\n\n        var ani = ele.animation( properties, (queue ? { queue: true } : undefined) );\n\n        ani.play();\n      }\n\n      return this; // chaining\n    };\n  }, // animate\n\n  stop: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function stopImpl( clearQueue, jumpToEnd ){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      for( var i = 0; i < all.length; i++ ){\n        var ele = all[i];\n        var _p = ele._private;\n        var anis = _p.animation.current;\n\n        for( var j = 0; j < anis.length; j++ ){\n          var ani = anis[j];\n          var ani_p = ani._private;\n\n          if( jumpToEnd ){\n            // next iteration of the animation loop, the animation\n            // will go straight to the end and be removed\n            ani_p.duration = 0;\n          }\n        }\n\n        // clear the queue of future animations\n        if( clearQueue ){\n          _p.animation.queue = [];\n        }\n\n        if( !jumpToEnd ){\n          _p.animation.current = [];\n        }\n      }\n\n      // we have to notify (the animation loop doesn't do it for us on `stop`)\n      cy.notify({\n        collection: this,\n        type: 'draw'\n      });\n\n      return this;\n    };\n  } // stop\n\n}; // define\n\nmodule.exports = define;\n\n},{\"./animation\":1,\"./event\":42,\"./is\":77,\"./promise\":80,\"./selector\":81,\"./util\":94}],42:[function(_dereq_,module,exports){\n'use strict';\n\n// ref\n// https://github.com/jquery/jquery/blob/master/src/event.js\n\nvar Event = function( src, props ) {\n  // Allow instantiation without the 'new' keyword\n  if ( !(this instanceof Event) ) {\n    return new Event( src, props );\n  }\n\n  // Event object\n  if ( src && src.type ) {\n    this.originalEvent = src;\n    this.type = src.type;\n\n    // Events bubbling up the document may have been marked as prevented\n    // by a handler lower down the tree; reflect the correct value.\n    this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse;\n\n  // Event type\n  } else {\n    this.type = src;\n  }\n\n  // Put explicitly provided properties onto the event object\n  if ( props ) {\n    // util.extend( this, props );\n\n    // more efficient to manually copy fields we use\n    this.type = props.type !== undefined ? props.type : this.type;\n    this.cy = props.cy;\n    this.cyTarget = props.cyTarget;\n    this.cyPosition = props.cyPosition;\n    this.cyRenderedPosition = props.cyRenderedPosition;\n    this.namespace = props.namespace;\n    this.layout = props.layout;\n    this.data = props.data;\n    this.message = props.message;\n  }\n\n  // Create a timestamp if incoming event doesn't have one\n  this.timeStamp = src && src.timeStamp || Date.now();\n};\n\nfunction returnFalse() {\n  return false;\n}\n\nfunction returnTrue() {\n  return true;\n}\n\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\nEvent.prototype = {\n  instanceString: function(){\n    return 'event';\n  },\n\n  preventDefault: function() {\n    this.isDefaultPrevented = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n\n    // if preventDefault exists run it on the original event\n    if ( e.preventDefault ) {\n      e.preventDefault();\n    }\n  },\n\n  stopPropagation: function() {\n    this.isPropagationStopped = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n\n    // if stopPropagation exists run it on the original event\n    if ( e.stopPropagation ) {\n      e.stopPropagation();\n    }\n  },\n\n  stopImmediatePropagation: function() {\n    this.isImmediatePropagationStopped = returnTrue;\n    this.stopPropagation();\n  },\n\n  isDefaultPrevented: returnFalse,\n  isPropagationStopped: returnFalse,\n  isImmediatePropagationStopped: returnFalse\n};\n\nmodule.exports = Event;\n\n},{}],43:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('./util');\nvar define = _dereq_('./define');\nvar Collection = _dereq_('./collection');\nvar Core = _dereq_('./core');\nvar incExts = _dereq_('./extensions');\nvar is = _dereq_('./is');\n\n// registered extensions to cytoscape, indexed by name\nvar extensions = {};\n\n// registered modules for extensions, indexed by name\nvar modules = {};\n\nfunction setExtension( type, name, registrant ){\n\n  var ext = registrant;\n\n  if( type === 'core' ){\n    Core.prototype[ name ] = registrant;\n\n  } else if( type === 'collection' ){\n    Collection.prototype[ name ] = registrant;\n\n  } else if( type === 'layout' ){\n    // fill in missing layout functions in the prototype\n\n    var Layout = function( options ){\n      this.options = options;\n\n      registrant.call( this, options );\n\n      // make sure layout has _private for use w/ std apis like .on()\n      if( !is.plainObject(this._private) ){\n        this._private = {};\n      }\n\n      this._private.cy = options.cy;\n      this._private.listeners = [];\n    };\n\n    var layoutProto = Layout.prototype = Object.create( registrant.prototype );\n\n    var optLayoutFns = [];\n\n    for( var i = 0; i < optLayoutFns.length; i++ ){\n      var fnName = optLayoutFns[i];\n\n      layoutProto[fnName] = layoutProto[fnName] || function(){ return this; };\n    }\n\n    // either .start() or .run() is defined, so autogen the other\n    if( layoutProto.start && !layoutProto.run ){\n      layoutProto.run = function(){ this.start(); return this; };\n    } else if( !layoutProto.start && layoutProto.run ){\n      layoutProto.start = function(){ this.run(); return this; };\n    }\n\n    if( !layoutProto.stop ){\n      layoutProto.stop = function(){\n        var opts = this.options;\n\n        if( opts && opts.animate ){\n          var anis = this.animations;\n          for( var i = 0; i < anis.length; i++ ){\n            anis[i].stop();\n          }\n        }\n\n        this.trigger('layoutstop');\n\n        return this;\n      };\n    }\n\n    if( !layoutProto.destroy ){\n      layoutProto.destroy = function(){\n        return this;\n      };\n    }\n\n    layoutProto.on = define.on({ layout: true });\n    layoutProto.one = define.on({ layout: true, unbindSelfOnTrigger: true });\n    layoutProto.once = define.on({ layout: true, unbindAllBindersOnTrigger: true });\n    layoutProto.off = define.off({ layout: true });\n    layoutProto.trigger = define.trigger({ layout: true });\n\n    define.eventAliasesOn( layoutProto );\n\n    ext = Layout; // replace with our wrapped layout\n\n  } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){\n    // user registered renderers inherit from base\n\n    var bProto = getExtension( 'renderer', 'base' ).prototype;\n    var rProto = registrant.prototype;\n\n    for( var pName in bProto ){\n      var pVal = bProto[ pName ];\n      var existsInR = rProto[ pName ] != null;\n\n      if( existsInR ){\n        util.error('Can not register renderer `' + name + '` since it overrides `' + pName + '` in its prototype');\n        return;\n      }\n\n      rProto[ pName ] = pVal; // take impl from base\n    }\n\n    bProto.clientFunctions.forEach(function( name ){\n      rProto[ name ] = rProto[ name ] || function(){\n        util.error('Renderer does not implement `renderer.' + name + '()` on its prototype');\n      };\n    });\n\n  }\n\n  return util.setMap({\n    map: extensions,\n    keys: [ type, name ],\n    value: ext\n  });\n}\n\nfunction getExtension(type, name){\n  return util.getMap({\n    map: extensions,\n    keys: [ type, name ]\n  });\n}\n\nfunction setModule(type, name, moduleType, moduleName, registrant){\n  return util.setMap({\n    map: modules,\n    keys: [ type, name, moduleType, moduleName ],\n    value: registrant\n  });\n}\n\nfunction getModule(type, name, moduleType, moduleName){\n  return util.getMap({\n    map: modules,\n    keys: [ type, name, moduleType, moduleName ]\n  });\n}\n\nvar extension = function(){\n  // e.g. extension('renderer', 'svg')\n  if( arguments.length === 2 ){\n    return getExtension.apply(null, arguments);\n  }\n\n  // e.g. extension('renderer', 'svg', { ... })\n  else if( arguments.length === 3 ){\n    return setExtension.apply(null, arguments);\n  }\n\n  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')\n  else if( arguments.length === 4 ){\n    return getModule.apply(null, arguments);\n  }\n\n  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })\n  else if( arguments.length === 5 ){\n    return setModule.apply(null, arguments);\n  }\n\n  else {\n    util.error('Invalid extension access syntax');\n  }\n\n};\n\n// allows a core instance to access extensions internally\nCore.prototype.extension = extension;\n\n// included extensions\nincExts.forEach(function( group ){\n  group.extensions.forEach(function( ext ){\n    setExtension( group.type, ext.name, ext.impl );\n  });\n});\n\nmodule.exports = extension;\n\n},{\"./collection\":23,\"./core\":34,\"./define\":41,\"./extensions\":44,\"./is\":77,\"./util\":94}],44:[function(_dereq_,module,exports){\n'use strict';\n\nmodule.exports = [\n  {\n    type: 'layout',\n    extensions: _dereq_('./layout')\n  },\n\n  {\n    type: 'renderer',\n    extensions: _dereq_('./renderer')\n  }\n];\n\n},{\"./layout\":50,\"./renderer\":72}],45:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\nvar math = _dereq_('../../math');\nvar is = _dereq_('../../is');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)\n  padding: 30, // padding on fit\n  circle: false, // put depths in concentric circles if true, put depths top down if false\n  spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap)\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n  roots: undefined, // the roots of the trees\n  maximalAdjustments: 0, // how many times to try to position the nodes in a maximal way (i.e. no backtracking)\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction BreadthFirstLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nBreadthFirstLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var cy = params.cy;\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n  var graph = eles;\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var roots;\n  if( is.elementOrCollection(options.roots) ){\n    roots = options.roots;\n  } else if( is.array(options.roots) ){\n    var rootsArray = [];\n\n    for( var i = 0; i < options.roots.length; i++ ){\n      var id = options.roots[i];\n      var ele = cy.getElementById( id );\n      rootsArray.push( ele );\n    }\n\n    roots = cy.collection( rootsArray );\n  } else if( is.string(options.roots) ){\n    roots = cy.$( options.roots );\n\n  } else {\n    if( options.directed ){\n      roots = nodes.roots();\n    } else {\n      var components = [];\n      var unhandledNodes = nodes;\n\n      while( unhandledNodes.length > 0 ){\n        var currComp = cy.collection();\n\n        eles.bfs({\n          roots: unhandledNodes[0],\n          visit: function(i, depth, node, edge, pNode){\n            currComp = currComp.add( node );\n          },\n          directed: false\n        });\n\n        unhandledNodes = unhandledNodes.not( currComp );\n        components.push( currComp );\n      }\n\n      roots = cy.collection();\n      for( var i = 0; i < components.length; i++ ){\n        var comp = components[i];\n        var maxDegree = comp.maxDegree( false );\n        var compRoots = comp.filter(function(){\n          return this.degree(false) === maxDegree;\n        });\n\n        roots = roots.add( compRoots );\n      }\n\n    }\n  }\n\n\n  var depths = [];\n  var foundByBfs = {};\n  var id2depth = {};\n  var prevNode = {};\n  var prevEdge = {};\n  var successors = {};\n\n  // find the depths of the nodes\n  graph.bfs({\n    roots: roots,\n    directed: options.directed,\n    visit: function(i, depth, node, edge, pNode){\n      var ele = this[0];\n      var id = ele.id();\n\n      if( !depths[depth] ){\n        depths[depth] = [];\n      }\n\n      depths[depth].push( ele );\n      foundByBfs[ id ] = true;\n      id2depth[ id ] = depth;\n      prevNode[ id ] = pNode;\n      prevEdge[ id ] = edge;\n\n      if( pNode ){\n        var prevId = pNode.id();\n        var succ = successors[ prevId ] = successors[ prevId ] || [];\n\n        succ.push( node );\n      }\n    }\n  });\n\n  // check for nodes not found by bfs\n  var orphanNodes = [];\n  for( var i = 0; i < nodes.length; i++ ){\n    var ele = nodes[i];\n\n    if( foundByBfs[ ele.id() ] ){\n      continue;\n    } else {\n      orphanNodes.push( ele );\n    }\n  }\n\n  // assign orphan nodes a depth from their neighborhood\n  var maxChecks = orphanNodes.length * 3;\n  var checks = 0;\n  while( orphanNodes.length !== 0 && checks < maxChecks ){\n    var node = orphanNodes.shift();\n    var neighbors = node.neighborhood().nodes();\n    var assignedDepth = false;\n\n    for( var i = 0; i < neighbors.length; i++ ){\n      var depth = id2depth[ neighbors[i].id() ];\n\n      if( depth !== undefined ){\n        depths[depth].push( node );\n        assignedDepth = true;\n        break;\n      }\n    }\n\n    if( !assignedDepth ){\n      orphanNodes.push( node );\n    }\n\n    checks++;\n  }\n\n  // assign orphan nodes that are still left to the depth of their subgraph\n  while( orphanNodes.length !== 0 ){\n    var node = orphanNodes.shift();\n    //var subgraph = graph.bfs( node ).path;\n    var assignedDepth = false;\n\n    // for( var i = 0; i < subgraph.length; i++ ){\n    //   var depth = id2depth[ subgraph[i].id() ];\n\n    //   if( depth !== undefined ){\n    //     depths[depth].push( node );\n    //     assignedDepth = true;\n    //     break;\n    //   }\n    // }\n\n    if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0\n      if( depths.length === 0 ){\n        depths.push([]);\n      }\n\n      depths[0].push( node );\n    }\n  }\n\n  // assign the nodes a depth and index\n  var assignDepthsToEles = function(){\n    for( var i = 0; i < depths.length; i++ ){\n      var eles = depths[i];\n\n      for( var j = 0; j < eles.length; j++ ){\n        var ele = eles[j];\n\n        ele._private.scratch.breadthfirst = {\n          depth: i,\n          index: j\n        };\n      }\n    }\n  };\n  assignDepthsToEles();\n\n\n  var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth\n    var edges = node.connectedEdges(function(){\n      return this.data('target') === node.id();\n    });\n    var thisInfo = node._private.scratch.breadthfirst;\n    var highestDepthOfOther = 0;\n    var highestOther;\n    for( var i = 0; i < edges.length; i++ ){\n      var edge = edges[i];\n      var otherNode = edge.source()[0];\n      var otherInfo = otherNode._private.scratch.breadthfirst;\n\n      if( thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth ){\n        highestDepthOfOther = otherInfo.depth;\n        highestOther = otherNode;\n      }\n    }\n\n    return highestOther;\n  };\n\n   // make maximal if so set by adjusting depths\n  for( var adj = 0; adj < options.maximalAdjustments; adj++ ){\n\n    var nDepths = depths.length;\n    var elesToMove = [];\n    for( var i = 0; i < nDepths; i++ ){\n      var depth = depths[i];\n\n      var nDepth = depth.length;\n      for( var j = 0; j < nDepth; j++ ){\n        var ele = depth[j];\n        var info = ele._private.scratch.breadthfirst;\n        var intEle = intersectsDepth(ele);\n\n        if( intEle ){\n          info.intEle = intEle;\n          elesToMove.push( ele );\n        }\n      }\n    }\n\n    for( var i = 0; i < elesToMove.length; i++ ){\n      var ele = elesToMove[i];\n      var info = ele._private.scratch.breadthfirst;\n      var intEle = info.intEle;\n      var intInfo = intEle._private.scratch.breadthfirst;\n\n      depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index\n\n      // add to end of new depth\n      var newDepth = intInfo.depth + 1;\n      while( newDepth > depths.length - 1 ){\n        depths.push([]);\n      }\n      depths[ newDepth ].push( ele );\n\n      info.depth = newDepth;\n      info.index = depths[newDepth].length - 1;\n    }\n\n    assignDepthsToEles();\n  }\n\n  // find min distance we need to leave between nodes\n  var minDistance = 0;\n  if( options.avoidOverlap ){\n    for( var i = 0; i < nodes.length; i++ ){\n      var n = nodes[i];\n      var nbb = n.boundingBox();\n      var w = nbb.w;\n      var h = nbb.h;\n\n      minDistance = Math.max(minDistance, w, h);\n    }\n    minDistance *= options.spacingFactor; // just to have some nice spacing\n  }\n\n  // get the weighted percent for an element based on its connectivity to other levels\n  var cachedWeightedPercent = {};\n  var getWeightedPercent = function( ele ){\n    if( cachedWeightedPercent[ ele.id() ] ){\n      return cachedWeightedPercent[ ele.id() ];\n    }\n\n    var eleDepth = ele._private.scratch.breadthfirst.depth;\n    var neighbors = ele.neighborhood().nodes().not(':parent');\n    var percent = 0;\n    var samples = 0;\n\n    for( var i = 0; i < neighbors.length; i++ ){\n      var neighbor = neighbors[i];\n      var bf = neighbor._private.scratch.breadthfirst;\n      var index = bf.index;\n      var depth = bf.depth;\n      var nDepth = depths[depth].length;\n\n      if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above\n        percent += index / nDepth;\n        samples++;\n      }\n    }\n\n    samples = Math.max(1, samples);\n    percent = percent / samples;\n\n    if( samples === 0 ){ // so lone nodes have a \"don't care\" state in sorting\n      percent = undefined;\n    }\n\n    cachedWeightedPercent[ ele.id() ] = percent;\n    return percent;\n  };\n\n\n  // rearrange the indices in each depth level based on connectivity\n\n  var sortFn = function(a, b){\n    var apct = getWeightedPercent( a );\n    var bpct = getWeightedPercent( b );\n\n    return apct - bpct;\n  };\n\n  for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result\n\n    for( var i = 0; i < depths.length; i++ ){\n      depths[i] = depths[i].sort( sortFn );\n    }\n    assignDepthsToEles(); // and update\n\n  }\n\n  var biggestDepthSize = 0;\n  for( var i = 0; i < depths.length; i++ ){\n    biggestDepthSize = Math.max( depths[i].length, biggestDepthSize );\n  }\n\n  var center = {\n    x: bb.x1 + bb.w/2,\n    y: bb.x1 + bb.h/2\n  };\n\n  var getPosition = function( ele, isBottomDepth ){\n    var info = ele._private.scratch.breadthfirst;\n    var depth = info.depth;\n    var index = info.index;\n    var depthSize = depths[depth].length;\n\n    var distanceX = Math.max( bb.w / (depthSize + 1), minDistance );\n    var distanceY = Math.max( bb.h / (depths.length + 1), minDistance );\n    var radiusStepSize = Math.min( bb.w / 2 / depths.length, bb.h / 2 / depths.length );\n    radiusStepSize = Math.max( radiusStepSize, minDistance );\n\n    if( !options.circle ){\n\n      var epos = {\n        x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,\n        y: (depth + 1) * distanceY\n      };\n\n      if( isBottomDepth ){\n        return epos;\n      }\n\n      // var succs = successors[ ele.id() ];\n      // if( succs ){\n      //   epos.x = 0;\n      //\n      //   for( var i = 0 ; i < succs.length; i++ ){\n      //     var spos = pos[ succs[i].id() ];\n      //\n      //     epos.x += spos.x;\n      //   }\n      //\n      //   epos.x /= succs.length;\n      // } else {\n      //   //debugger;\n      // }\n\n      return epos;\n\n    } else {\n      if( options.circle ){\n        var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize/2 : 0);\n        var theta = 2 * Math.PI / depths[depth].length * index;\n\n        if( depth === 0 && depths[0].length === 1 ){\n          radius = 1;\n        }\n\n        return {\n          x: center.x + radius * Math.cos(theta),\n          y: center.y + radius * Math.sin(theta)\n        };\n\n      } else {\n        return {\n          x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,\n          y: (depth + 1) * distanceY\n        };\n      }\n    }\n\n  };\n\n  // get positions in reverse depth order\n  var pos = {};\n  for( var i = depths.length - 1; i >=0; i-- ){\n    var depth = depths[i];\n\n    for( var j = 0; j < depth.length; j++ ){\n      var node = depth[j];\n\n      pos[ node.id() ] = getPosition( node, i === depths.length - 1 );\n    }\n  }\n\n  nodes.layoutPositions(this, options, function(){\n    return pos[ this.id() ];\n  });\n\n  return this; // chaining\n};\n\nmodule.exports = BreadthFirstLayout;\n\n},{\"../../is\":77,\"../../math\":79,\"../../util\":94}],46:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\nvar math = _dereq_('../../math');\nvar is = _dereq_('../../is');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  padding: 30, // the padding on fit\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space\n  radius: undefined, // the radius of the circle\n  startAngle: 3/2 * Math.PI, // where nodes start in radians\n  sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)\n  clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n  sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction CircleLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nCircleLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var cy = params.cy;\n  var eles = options.eles;\n\n  var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n\n  var nodes = eles.nodes().not(':parent');\n\n  if( options.sort ){\n    nodes = nodes.sort( options.sort );\n  }\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var center = {\n    x: bb.x1 + bb.w/2,\n    y: bb.y1 + bb.h/2\n  };\n\n  var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/nodes.length : options.sweep;\n\n  var dTheta = sweep / ( Math.max(1, nodes.length - 1) );\n  var r;\n\n  var minDistance = 0;\n  for( var i = 0; i < nodes.length; i++ ){\n    var n = nodes[i];\n    var nbb = n.boundingBox();\n    var w = nbb.w;\n    var h = nbb.h;\n\n    minDistance = Math.max(minDistance, w, h);\n  }\n\n  if( is.number(options.radius) ){\n    r = options.radius;\n  } else if( nodes.length <= 1 ){\n    r = 0;\n  } else {\n    r = Math.min( bb.h, bb.w )/2 - minDistance;\n  }\n\n  // calculate the radius\n  if( nodes.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)\n    minDistance *= 1.75; // just to have some nice spacing\n\n    var dcos = Math.cos(dTheta) - Math.cos(0);\n    var dsin = Math.sin(dTheta) - Math.sin(0);\n    var rMin = Math.sqrt( minDistance * minDistance / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping\n    r = Math.max( rMin, r );\n  }\n\n  var getPos = function( i, ele ){\n    var theta = options.startAngle + i * dTheta * ( clockwise ? 1 : -1 );\n\n    var rx = r * Math.cos( theta );\n    var ry = r * Math.sin( theta );\n    var pos = {\n      x: center.x + rx,\n      y: center.y + ry\n    };\n\n    return pos;\n  };\n\n  nodes.layoutPositions( this, options, getPos );\n\n  return this; // chaining\n};\n\nmodule.exports = CircleLayout;\n\n},{\"../../is\":77,\"../../math\":79,\"../../util\":94}],47:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\nvar math = _dereq_('../../math');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  padding: 30, // the padding on fit\n  startAngle: 3/2 * Math.PI, // where nodes start in radians\n  sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)\n  clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n  equidistant: false, // whether levels have an equal radial distance betwen them, may cause bounding box overflow\n  minNodeSpacing: 10, // min spacing between outside of nodes (used for radius adjustment)\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n  height: undefined, // height of layout area (overrides container height)\n  width: undefined, // width of layout area (overrides container width)\n  concentric: function(node){ // returns numeric value for each node, placing higher nodes in levels towards the centre\n    return node.degree();\n  },\n  levelWidth: function(nodes){ // the variation of concentric values in each level\n    return nodes.maxDegree() / 4;\n  },\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction ConcentricLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nConcentricLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n\n  var cy = params.cy;\n\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var center = {\n    x: bb.x1 + bb.w/2,\n    y: bb.y1 + bb.h/2\n  };\n\n  var nodeValues = []; // { node, value }\n  var theta = options.startAngle;\n  var maxNodeSize = 0;\n\n  for( var i = 0; i < nodes.length; i++ ){\n    var node = nodes[i];\n    var value;\n\n    // calculate the node value\n    value = options.concentric.apply(node, [ node ]);\n    nodeValues.push({\n      value: value,\n      node: node\n    });\n\n    // for style mapping\n    node._private.scratch.concentric = value;\n  }\n\n  // in case we used the `concentric` in style\n  nodes.updateStyle();\n\n  // calculate max size now based on potentially updated mappers\n  for( var i = 0; i < nodes.length; i++ ){\n    var node = nodes[i];\n    var nbb = node.boundingBox();\n\n    maxNodeSize = Math.max( maxNodeSize, nbb.w, nbb.h );\n  }\n\n  // sort node values in descreasing order\n  nodeValues.sort(function(a, b){\n    return b.value - a.value;\n  });\n\n  var levelWidth = options.levelWidth( nodes );\n\n  // put the values into levels\n  var levels = [ [] ];\n  var currentLevel = levels[0];\n  for( var i = 0; i < nodeValues.length; i++ ){\n    var val = nodeValues[i];\n\n    if( currentLevel.length > 0 ){\n      var diff = Math.abs( currentLevel[0].value - val.value );\n\n      if( diff >= levelWidth ){\n        currentLevel = [];\n        levels.push( currentLevel );\n      }\n    }\n\n    currentLevel.push( val );\n  }\n\n  // create positions from levels\n\n  var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes\n\n  if( !options.avoidOverlap ){ // then strictly constrain to bb\n    var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1;\n    var maxR = ( Math.min(bb.w, bb.h) / 2 - minDist );\n    var rStep = maxR / ( levels.length + firstLvlHasMulti ? 1 : 0 );\n\n    minDist = Math.min( minDist, rStep );\n  }\n\n  // find the metrics for each level\n  var r = 0;\n  for( var i = 0; i < levels.length; i++ ){\n    var level = levels[i];\n    var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/level.length : options.sweep;\n    var dTheta = level.dTheta = sweep / ( Math.max(1, level.length - 1) );\n\n    // calculate the radius\n    if( level.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)\n      var dcos = Math.cos(dTheta) - Math.cos(0);\n      var dsin = Math.sin(dTheta) - Math.sin(0);\n      var rMin = Math.sqrt( minDist * minDist / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping\n\n      r = Math.max( rMin, r );\n    }\n\n    level.r = r;\n\n    r += minDist;\n  }\n\n  if( options.equidistant ){\n    var rDeltaMax = 0;\n    var r = 0;\n\n    for( var i = 0; i < levels.length; i++ ){\n      var level = levels[i];\n      var rDelta = level.r - r;\n\n      rDeltaMax = Math.max( rDeltaMax, rDelta );\n    }\n\n    r = 0;\n    for( var i = 0; i < levels.length; i++ ){\n      var level = levels[i];\n\n      if( i === 0 ){\n        r = level.r;\n      }\n\n      level.r = r;\n\n      r += rDeltaMax;\n    }\n  }\n\n  // calculate the node positions\n  var pos = {}; // id => position\n  for( var i = 0; i < levels.length; i++ ){\n    var level = levels[i];\n    var dTheta = level.dTheta;\n    var r = level.r;\n\n    for( var j = 0; j < level.length; j++ ){\n      var val = level[j];\n      var theta = options.startAngle + (clockwise ? 1 : -1) * dTheta * j;\n\n      var p = {\n        x: center.x + r * Math.cos(theta),\n        y: center.y + r * Math.sin(theta)\n      };\n\n      pos[ val.node.id() ] = p;\n    }\n  }\n\n  // position the nodes\n  nodes.layoutPositions(this, options, function(){\n    var id = this.id();\n\n    return pos[id];\n  });\n\n  return this; // chaining\n};\n\nmodule.exports = ConcentricLayout;\n\n},{\"../../math\":79,\"../../util\":94}],48:[function(_dereq_,module,exports){\n'use strict';\n\n/*\nThe CoSE layout was written by Gerardo Huck.\nhttps://www.linkedin.com/in/gerardohuck/\n\nBased on the following article:\nhttp://dl.acm.org/citation.cfm?id=1498047\n\nModifications tracked on Github.\n*/\n\nvar util = _dereq_('../../util');\nvar math = _dereq_('../../math');\nvar Thread = _dereq_('../../thread');\nvar is = _dereq_('../../is');\n\nvar DEBUG;\n\n/**\n * @brief :  default layout options\n */\nvar defaults = {\n  // Called on `layoutready`\n  ready               : function() {},\n\n  // Called on `layoutstop`\n  stop                : function() {},\n\n  // Whether to animate while running the layout\n  animate             : true,\n\n  // The layout animates only after this many milliseconds\n  // (prevents flashing on fast runs)\n  animationThreshold  : 250,\n\n  // Number of iterations between consecutive screen positions update\n  // (0 -> only updated on the end)\n  refresh             : 20,\n\n  // Whether to fit the network view after when done\n  fit                 : true,\n\n  // Padding on fit\n  padding             : 30,\n\n  // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  boundingBox         : undefined,\n\n  // Extra spacing between components in non-compound graphs\n  componentSpacing    : 100,\n\n  // Node repulsion (non overlapping) multiplier\n  nodeRepulsion       : function( node ){ return 400000; },\n\n  // Node repulsion (overlapping) multiplier\n  nodeOverlap         : 10,\n\n  // Ideal edge (non nested) length\n  idealEdgeLength     : function( edge ){ return 10; },\n\n  // Divisor to compute edge forces\n  edgeElasticity      : function( edge ){ return 100; },\n\n  // Nesting factor (multiplier) to compute ideal edge length for nested edges\n  nestingFactor       : 5,\n\n  // Gravity force (constant)\n  gravity             : 80,\n\n  // Maximum number of iterations to perform\n  numIter             : 1000,\n\n  // Initial temperature (maximum node displacement)\n  initialTemp         : 200,\n\n  // Cooling factor (how the temperature is reduced between consecutive iterations\n  coolingFactor       : 0.95,\n\n  // Lower temperature threshold (below this point the layout will end)\n  minTemp             : 1.0,\n\n  // Whether to use threading to speed up the layout\n  useMultitasking     : true\n};\n\n\n/**\n * @brief       : constructor\n * @arg options : object containing layout options\n */\nfunction CoseLayout(options) {\n  this.options = util.extend({}, defaults, options);\n\n  this.options.layout = this;\n}\n\n\n/**\n * @brief : runs the layout\n */\nCoseLayout.prototype.run = function() {\n  var options = this.options;\n  var cy      = options.cy;\n  var layout  = this;\n  var thread  = this.thread;\n\n  if( !thread || thread.stopped() ){\n    thread = this.thread = Thread({ disabled: !options.useMultitasking });\n  }\n\n  layout.stopped = false;\n\n  layout.trigger({ type: 'layoutstart', layout: layout });\n\n  // Set DEBUG - Global variable\n  if (true === options.debug) {\n    DEBUG = true;\n  } else {\n    DEBUG = false;\n  }\n\n  // Initialize layout info\n  var layoutInfo = createLayoutInfo(cy, layout, options);\n\n  // Show LayoutInfo contents if debugging\n  if (DEBUG) {\n    printLayoutInfo(layoutInfo);\n  }\n\n  // If required, randomize node positions\n  // if (true === options.randomize) {\n    randomizePositions(layoutInfo, cy);\n  // }\n\n  var startTime = Date.now();\n  var refreshRequested = false;\n  var refresh = function( rOpts ){\n    rOpts = rOpts || {};\n\n    if( refreshRequested ){\n      return;\n    }\n\n    if( !rOpts.force && Date.now() - startTime < options.animationThreshold ){\n      return;\n    }\n\n    refreshRequested = true;\n\n    util.requestAnimationFrame(function(){\n      refreshPositions(layoutInfo, cy, options);\n\n      // Fit the graph if necessary\n      if (true === options.fit) {\n        cy.fit( options.padding );\n      }\n\n      refreshRequested = false;\n    });\n  };\n\n  thread.on('message', function( e ){\n    var layoutNodes = e.message;\n\n    layoutInfo.layoutNodes = layoutNodes;\n    refresh();\n  });\n\n  thread.pass({\n    layoutInfo: layoutInfo,\n    options: {\n      animate: options.animate,\n      refresh: options.refresh,\n      componentSpacing: options.componentSpacing,\n      nodeOverlap: options.nodeOverlap,\n      nestingFactor: options.nestingFactor,\n      gravity: options.gravity,\n      numIter: options.numIter,\n      initialTemp: options.initialTemp,\n      coolingFactor: options.coolingFactor,\n      minTemp: options.minTemp\n    }\n  }).run(function( pass ){\n    var layoutInfo = pass.layoutInfo;\n    var options = pass.options;\n    var stopped = false;\n\n    /**\n     * @brief          : Performs one iteration of the physical simulation\n     * @arg layoutInfo : LayoutInfo object already initialized\n     * @arg cy         : Cytoscape object\n     * @arg options    : Layout options\n     */\n    var step = function(layoutInfo, options, step) {\n      // var s = \"\\n\\n###############################\";\n      // s += \"\\nSTEP: \" + step;\n      // s += \"\\n###############################\\n\";\n      // logDebug(s);\n\n      // Calculate node repulsions\n      calculateNodeForces(layoutInfo, options);\n      // Calculate edge forces\n      calculateEdgeForces(layoutInfo, options);\n      // Calculate gravity forces\n      calculateGravityForces(layoutInfo, options);\n      // Propagate forces from parent to child\n      propagateForces(layoutInfo, options);\n      // Update positions based on calculated forces\n      updatePositions(layoutInfo, options);\n    };\n\n    /**\n     * @brief : Computes the node repulsion forces\n     */\n    var calculateNodeForces = function(layoutInfo, options) {\n      // Go through each of the graphs in graphSet\n      // Nodes only repel each other if they belong to the same graph\n      // var s = 'calculateNodeForces';\n      // logDebug(s);\n      for (var i = 0; i < layoutInfo.graphSet.length; i ++) {\n        var graph    = layoutInfo.graphSet[i];\n        var numNodes = graph.length;\n\n        // s = \"Set: \" + graph.toString();\n        // logDebug(s);\n\n        // Now get all the pairs of nodes\n        // Only get each pair once, (A, B) = (B, A)\n        for (var j = 0; j < numNodes; j++) {\n          var node1 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];\n\n          for (var k = j + 1; k < numNodes; k++) {\n            var node2 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[k]]];\n\n            nodeRepulsion(node1, node2, layoutInfo, options);\n          }\n        }\n      }\n    };\n\n    /**\n     * @brief : Compute the node repulsion forces between a pair of nodes\n     */\n    var nodeRepulsion = function(node1, node2, layoutInfo, options) {\n      // var s = \"Node repulsion. Node1: \" + node1.id + \" Node2: \" + node2.id;\n\n      var cmptId1 = node1.cmptId;\n      var cmptId2 = node2.cmptId;\n\n      if( cmptId1 !== cmptId2 && !layoutInfo.isCompound ){ return; }\n\n      // Get direction of line connecting both node centers\n      var directionX = node2.positionX - node1.positionX;\n      var directionY = node2.positionY - node1.positionY;\n      // s += \"\\ndirectionX: \" + directionX + \", directionY: \" + directionY;\n\n      // If both centers are the same, apply a random force\n      if (0 === directionX && 0 === directionY) {\n        // s += \"\\nNodes have the same position.\";\n        return; // TODO could be improved with random force\n      }\n\n      var overlap = nodesOverlap(node1, node2, directionX, directionY);\n\n      if (overlap > 0) {\n        // s += \"\\nNodes DO overlap.\";\n        // s += \"\\nOverlap: \" + overlap;\n        // If nodes overlap, repulsion force is proportional\n        // to the overlap\n        var force    = options.nodeOverlap * overlap;\n\n        // Compute the module and components of the force vector\n        var distance = Math.sqrt(directionX * directionX + directionY * directionY);\n        // s += \"\\nDistance: \" + distance;\n        var forceX   = force * directionX / distance;\n        var forceY   = force * directionY / distance;\n\n      } else {\n        // s += \"\\nNodes do NOT overlap.\";\n        // If there's no overlap, force is inversely proportional\n        // to squared distance\n\n        // Get clipping points for both nodes\n        var point1 = findClippingPoint(node1, directionX, directionY);\n        var point2 = findClippingPoint(node2, -1 * directionX, -1 * directionY);\n\n        // Use clipping points to compute distance\n        var distanceX   = point2.x - point1.x;\n        var distanceY   = point2.y - point1.y;\n        var distanceSqr = distanceX * distanceX + distanceY * distanceY;\n        var distance    = Math.sqrt(distanceSqr);\n        // s += \"\\nDistance: \" + distance;\n\n        // Compute the module and components of the force vector\n        var force  = ( node1.nodeRepulsion + node2.nodeRepulsion ) / distanceSqr;\n        var forceX = force * distanceX / distance;\n        var forceY = force * distanceY / distance;\n      }\n\n      // Apply force\n      if( !node1.isLocked ){\n        node1.offsetX -= forceX;\n        node1.offsetY -= forceY;\n      }\n\n      if( !node2.isLocked ){\n        node2.offsetX += forceX;\n        node2.offsetY += forceY;\n      }\n\n      // s += \"\\nForceX: \" + forceX + \" ForceY: \" + forceY;\n      // logDebug(s);\n\n      return;\n    };\n\n    /**\n     * @brief  : Determines whether two nodes overlap or not\n     * @return : Amount of overlapping (0 => no overlap)\n     */\n    var nodesOverlap = function(node1, node2, dX, dY) {\n\n      if (dX > 0) {\n        var overlapX = node1.maxX - node2.minX;\n      } else {\n        var overlapX = node2.maxX - node1.minX;\n      }\n\n      if (dY > 0) {\n        var overlapY = node1.maxY - node2.minY;\n      } else {\n        var overlapY = node2.maxY - node1.minY;\n      }\n\n      if (overlapX >= 0 && overlapY >= 0) {\n        return Math.sqrt(overlapX * overlapX + overlapY * overlapY);\n      } else {\n        return 0;\n      }\n    };\n\n    /**\n     * @brief : Finds the point in which an edge (direction dX, dY) intersects\n     *          the rectangular bounding box of it's source/target node\n     */\n    var findClippingPoint = function(node, dX, dY) {\n\n      // Shorcuts\n      var X = node.positionX;\n      var Y = node.positionY;\n      var H = node.height || 1;\n      var W = node.width || 1;\n      var dirSlope     = dY / dX;\n      var nodeSlope    = H / W;\n\n      // var s = 'Computing clipping point of node ' + node.id +\n      //   \" . Height:  \" + H + \", Width: \" + W +\n      //   \"\\nDirection \" + dX + \", \" + dY;\n      //\n      // Compute intersection\n      var res = {};\n      do {\n        // Case: Vertical direction (up)\n        if (0 === dX && 0 < dY) {\n          res.x = X;\n          // s += \"\\nUp direction\";\n          res.y = Y + H / 2;\n          break;\n        }\n\n        // Case: Vertical direction (down)\n        if (0 === dX && 0 > dY) {\n          res.x = X;\n          res.y = Y + H / 2;\n          // s += \"\\nDown direction\";\n          break;\n        }\n\n        // Case: Intersects the right border\n        if (0 < dX &&\n        -1 * nodeSlope <= dirSlope &&\n        dirSlope <= nodeSlope) {\n          res.x = X + W / 2;\n          res.y = Y + (W * dY / 2 / dX);\n          // s += \"\\nRightborder\";\n          break;\n        }\n\n        // Case: Intersects the left border\n        if (0 > dX &&\n        -1 * nodeSlope <= dirSlope &&\n        dirSlope <= nodeSlope) {\n          res.x = X - W / 2;\n          res.y = Y - (W * dY / 2 / dX);\n          // s += \"\\nLeftborder\";\n          break;\n        }\n\n        // Case: Intersects the top border\n        if (0 < dY &&\n        ( dirSlope <= -1 * nodeSlope ||\n          dirSlope >= nodeSlope )) {\n          res.x = X + (H * dX / 2 / dY);\n          res.y = Y + H / 2;\n          // s += \"\\nTop border\";\n          break;\n        }\n\n        // Case: Intersects the bottom border\n        if (0 > dY &&\n        ( dirSlope <= -1 * nodeSlope ||\n          dirSlope >= nodeSlope )) {\n          res.x = X - (H * dX / 2 / dY);\n          res.y = Y - H / 2;\n          // s += \"\\nBottom border\";\n          break;\n        }\n\n      } while (false);\n\n      // s += \"\\nClipping point found at \" + res.x + \", \" + res.y;\n      // logDebug(s);\n      return res;\n    };\n\n    /**\n     * @brief : Calculates all edge forces\n     */\n    var calculateEdgeForces = function(layoutInfo, options) {\n      // Iterate over all edges\n      for (var i = 0; i < layoutInfo.edgeSize; i++) {\n        // Get edge, source & target nodes\n        var edge     = layoutInfo.layoutEdges[i];\n        var sourceIx = layoutInfo.idToIndex[edge.sourceId];\n        var source   = layoutInfo.layoutNodes[sourceIx];\n        var targetIx = layoutInfo.idToIndex[edge.targetId];\n        var target   = layoutInfo.layoutNodes[targetIx];\n\n        // Get direction of line connecting both node centers\n        var directionX = target.positionX - source.positionX;\n        var directionY = target.positionY - source.positionY;\n\n        // If both centers are the same, do nothing.\n        // A random force has already been applied as node repulsion\n        if (0 === directionX && 0 === directionY) {\n        return;\n        }\n\n        // Get clipping points for both nodes\n        var point1 = findClippingPoint(source, directionX, directionY);\n        var point2 = findClippingPoint(target, -1 * directionX, -1 * directionY);\n\n\n        var lx = point2.x - point1.x;\n        var ly = point2.y - point1.y;\n        var l  = Math.sqrt(lx * lx + ly * ly);\n\n        var force  = Math.pow(edge.idealLength - l, 2) / edge.elasticity;\n\n        if (0 !== l) {\n          var forceX = force * lx / l;\n          var forceY = force * ly / l;\n        } else {\n          var forceX = 0;\n          var forceY = 0;\n        }\n\n        // Add this force to target and source nodes\n        if( !source.isLocked ){\n          source.offsetX += forceX;\n          source.offsetY += forceY;\n        }\n\n        if( !target.isLocked ){\n          target.offsetX -= forceX;\n          target.offsetY -= forceY;\n        }\n\n        // var s = 'Edge force between nodes ' + source.id + ' and ' + target.id;\n        // s += \"\\nDistance: \" + l + \" Force: (\" + forceX + \", \" + forceY + \")\";\n        // logDebug(s);\n      }\n    };\n\n    /**\n     * @brief : Computes gravity forces for all nodes\n     */\n    var calculateGravityForces = function(layoutInfo, options) {\n      var distThreshold = 1;\n\n      // var s = 'calculateGravityForces';\n      // logDebug(s);\n      for (var i = 0; i < layoutInfo.graphSet.length; i ++) {\n        var graph    = layoutInfo.graphSet[i];\n        var numNodes = graph.length;\n\n        // s = \"Set: \" + graph.toString();\n        // logDebug(s);\n\n        // Compute graph center\n        if (0 === i) {\n          var centerX   = layoutInfo.clientHeight / 2;\n          var centerY   = layoutInfo.clientWidth  / 2;\n        } else {\n          // Get Parent node for this graph, and use its position as center\n          var temp    = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[0]]];\n          var parent  = layoutInfo.layoutNodes[layoutInfo.idToIndex[temp.parentId]];\n          var centerX = parent.positionX;\n          var centerY = parent.positionY;\n        }\n        // s = \"Center found at: \" + centerX + \", \" + centerY;\n        // logDebug(s);\n\n        // Apply force to all nodes in graph\n        for (var j = 0; j < numNodes; j++) {\n          var node = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];\n          // s = \"Node: \" + node.id;\n\n          if( node.isLocked ){ continue; }\n\n          var dx = centerX - node.positionX;\n          var dy = centerY - node.positionY;\n          var d  = Math.sqrt(dx * dx + dy * dy);\n          if (d > distThreshold) {\n            var fx = options.gravity * dx / d;\n            var fy = options.gravity * dy / d;\n            node.offsetX += fx;\n            node.offsetY += fy;\n            // s += \": Applied force: \" + fx + \", \" + fy;\n          } else {\n            // s += \": skypped since it's too close to center\";\n          }\n          // logDebug(s);\n        }\n      }\n    };\n\n    /**\n     * @brief          : This function propagates the existing offsets from\n     *                   parent nodes to its descendents.\n     * @arg layoutInfo : layoutInfo Object\n     * @arg cy         : cytoscape Object\n     * @arg options    : Layout options\n     */\n    var propagateForces = function(layoutInfo, options) {\n      // Inline implementation of a queue, used for traversing the graph in BFS order\n      var queue = [];\n      var start = 0;   // Points to the start the queue\n      var end   = -1;  // Points to the end of the queue\n\n      // logDebug('propagateForces');\n\n      // Start by visiting the nodes in the root graph\n      queue.push.apply(queue, layoutInfo.graphSet[0]);\n      end += layoutInfo.graphSet[0].length;\n\n      // Traverse the graph, level by level,\n      while (start <= end) {\n        // Get the node to visit and remove it from queue\n        var nodeId    = queue[start++];\n        var nodeIndex = layoutInfo.idToIndex[nodeId];\n        var node      = layoutInfo.layoutNodes[nodeIndex];\n        var children  = node.children;\n\n        // We only need to process the node if it's compound\n        if (0 < children.length && !node.isLocked) {\n          var offX = node.offsetX;\n          var offY = node.offsetY;\n\n          // var s = \"Propagating offset from parent node : \" + node.id +\n          //   \". OffsetX: \" + offX + \". OffsetY: \" + offY;\n          // s += \"\\n Children: \" + children.toString();\n          // logDebug(s);\n\n          for (var i = 0; i < children.length; i++) {\n            var childNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[children[i]]];\n            // Propagate offset\n            childNode.offsetX += offX;\n            childNode.offsetY += offY;\n            // Add children to queue to be visited\n            queue[++end] = children[i];\n          }\n\n          // Reset parent offsets\n          node.offsetX = 0;\n          node.offsetY = 0;\n        }\n\n      }\n    };\n\n    /**\n     * @brief : Updates the layout model positions, based on\n     *          the accumulated forces\n     */\n    var updatePositions = function(layoutInfo, options) {\n      // var s = 'Updating positions';\n      // logDebug(s);\n\n      // Reset boundaries for compound nodes\n      for (var i = 0; i < layoutInfo.nodeSize; i++) {\n        var n = layoutInfo.layoutNodes[i];\n        if (0 < n.children.length) {\n          // logDebug(\"Resetting boundaries of compound node: \" + n.id);\n          n.maxX = undefined;\n          n.minX = undefined;\n          n.maxY = undefined;\n          n.minY = undefined;\n        }\n      }\n\n      for (var i = 0; i < layoutInfo.nodeSize; i++) {\n        var n = layoutInfo.layoutNodes[i];\n        if (0 < n.children.length || n.isLocked) {\n          // No need to set compound or locked node position\n          // logDebug(\"Skipping position update of node: \" + n.id);\n          continue;\n        }\n        // s = \"Node: \" + n.id + \" Previous position: (\" +\n        // n.positionX + \", \" + n.positionY + \").\";\n\n        // Limit displacement in order to improve stability\n        var tempForce = limitForce(n.offsetX, n.offsetY, layoutInfo.temperature);\n        n.positionX += tempForce.x;\n        n.positionY += tempForce.y;\n        n.offsetX = 0;\n        n.offsetY = 0;\n        n.minX    = n.positionX - n.width;\n        n.maxX    = n.positionX + n.width;\n        n.minY    = n.positionY - n.height;\n        n.maxY    = n.positionY + n.height;\n        // s += \" New Position: (\" + n.positionX + \", \" + n.positionY + \").\";\n        // logDebug(s);\n\n        // Update ancestry boudaries\n        updateAncestryBoundaries(n, layoutInfo);\n      }\n\n      // Update size, position of compund nodes\n      for (var i = 0; i < layoutInfo.nodeSize; i++) {\n        var n = layoutInfo.layoutNodes[i];\n        if ( 0 < n.children.length && !n.isLocked ) {\n          n.positionX = (n.maxX + n.minX) / 2;\n          n.positionY = (n.maxY + n.minY) / 2;\n          n.width     = n.maxX - n.minX;\n          n.height    = n.maxY - n.minY;\n          // s = \"Updating position, size of compound node \" + n.id;\n          // s += \"\\nPositionX: \" + n.positionX + \", PositionY: \" + n.positionY;\n          // s += \"\\nWidth: \" + n.width + \", Height: \" + n.height;\n          // logDebug(s);\n        }\n      }\n    };\n\n    /**\n     * @brief : Limits a force (forceX, forceY) to be not\n     *          greater (in modulo) than max.\n     8          Preserves force direction.\n     */\n    var limitForce = function(forceX, forceY, max) {\n      // var s = \"Limiting force: (\" + forceX + \", \" + forceY + \"). Max: \" + max;\n      var force = Math.sqrt(forceX * forceX + forceY * forceY);\n\n      if (force > max) {\n        var res = {\n        x : max * forceX / force,\n        y : max * forceY / force\n        };\n\n      } else {\n        var res = {\n        x : forceX,\n        y : forceY\n        };\n      }\n\n      // s += \".\\nResult: (\" + res.x + \", \" + res.y + \")\";\n      // logDebug(s);\n\n      return res;\n    };\n\n    /**\n     * @brief : Function used for keeping track of compound node\n     *          sizes, since they should bound all their subnodes.\n     */\n    var updateAncestryBoundaries = function(node, layoutInfo) {\n      // var s = \"Propagating new position/size of node \" + node.id;\n      var parentId = node.parentId;\n      if (null == parentId) {\n        // If there's no parent, we are done\n        // s += \". No parent node.\";\n        // logDebug(s);\n        return;\n      }\n\n      // Get Parent Node\n      var p = layoutInfo.layoutNodes[layoutInfo.idToIndex[parentId]];\n      var flag = false;\n\n      // MaxX\n      if (null == p.maxX || node.maxX + p.padRight > p.maxX) {\n        p.maxX = node.maxX + p.padRight;\n        flag = true;\n        // s += \"\\nNew maxX for parent node \" + p.id + \": \" + p.maxX;\n      }\n\n      // MinX\n      if (null == p.minX || node.minX - p.padLeft < p.minX) {\n        p.minX = node.minX - p.padLeft;\n        flag = true;\n        // s += \"\\nNew minX for parent node \" + p.id + \": \" + p.minX;\n      }\n\n      // MaxY\n      if (null == p.maxY || node.maxY + p.padBottom > p.maxY) {\n        p.maxY = node.maxY + p.padBottom;\n        flag = true;\n        // s += \"\\nNew maxY for parent node \" + p.id + \": \" + p.maxY;\n      }\n\n      // MinY\n      if (null == p.minY || node.minY - p.padTop < p.minY) {\n        p.minY = node.minY - p.padTop;\n        flag = true;\n        // s += \"\\nNew minY for parent node \" + p.id + \": \" + p.minY;\n      }\n\n      // If updated boundaries, propagate changes upward\n      if (flag) {\n        // logDebug(s);\n        return updateAncestryBoundaries(p, layoutInfo);\n      }\n\n      // s += \". No changes in boundaries/position of parent node \" + p.id;\n      // logDebug(s);\n      return;\n    };\n\n    var separateComponents = function(layutInfo, options){\n      var nodes = layoutInfo.layoutNodes;\n      var components = [];\n\n      for( var i = 0; i < nodes.length; i++ ){\n        var node = nodes[i];\n        var cid = node.cmptId;\n        var component = components[ cid ] = components[ cid ] || [];\n\n        component.push( node );\n      }\n\n      var totalA = 0;\n\n      for( var i = 0; i < components.length; i++ ){\n        var c = components[i];\n        c.x1 = Infinity;\n        c.x2 = -Infinity;\n        c.y1 = Infinity;\n        c.y2 = -Infinity;\n\n        for( var j = 0; j < c.length; j++ ){\n          var n = c[j];\n\n          c.x1 = Math.min( c.x1, n.positionX - n.width/2 );\n          c.x2 = Math.max( c.x2, n.positionX + n.width/2 );\n          c.y1 = Math.min( c.y1, n.positionY - n.height/2 );\n          c.y2 = Math.max( c.y2, n.positionY + n.height/2 );\n        }\n\n        c.w = c.x2 - c.x1;\n        c.h = c.y2 - c.y1;\n\n        totalA += c.w * c.h;\n      }\n\n      components.sort(function( c1, c2 ){\n        return c2.w*c2.h - c1.w*c1.h;\n      });\n\n      var x = 0;\n      var y = 0;\n      var usedW = 0;\n      var rowH = 0;\n      var maxRowW = Math.sqrt( totalA ) * layoutInfo.clientWidth / layoutInfo.clientHeight;\n\n      for( var i = 0; i < components.length; i++ ){\n        var c = components[i];\n\n        for( var j = 0; j < c.length; j++ ){\n          var n = c[j];\n\n          if( !n.isLocked ){\n            n.positionX += x;\n            n.positionY += y;\n          }\n        }\n\n        x += c.w + options.componentSpacing;\n        usedW += c.w + options.componentSpacing;\n        rowH = Math.max( rowH, c.h );\n\n        if( usedW > maxRowW ){\n          y += rowH + options.componentSpacing;\n          x = 0;\n          usedW = 0;\n          rowH = 0;\n        }\n      }\n    };\n\n    var mainLoop = function(i){\n      if( stopped ){\n        // logDebug(\"Layout manually stopped. Stopping computation in step \" + i);\n        return false;\n      }\n\n      // Do one step in the phisical simulation\n      step(layoutInfo, options, i);\n\n      // Update temperature\n      layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor;\n      // logDebug(\"New temperature: \" + layoutInfo.temperature);\n\n      if (layoutInfo.temperature < options.minTemp) {\n        // logDebug(\"Temperature drop below minimum threshold. Stopping computation in step \" + i);\n        return false;\n      }\n\n      return true;\n    };\n\n    var i = 0;\n    var loopRet;\n\n    do {\n      var f = 0;\n\n      while( f < options.refresh && i < options.numIter ){\n        var loopRet = mainLoop(i);\n        if( !loopRet ){ break; }\n\n        f++;\n        i++;\n      }\n\n      if( options.animate ){\n        broadcast( layoutInfo.layoutNodes ); // jshint ignore:line\n      }\n\n    } while ( loopRet && i + 1 < options.numIter );\n\n    separateComponents( layoutInfo, options );\n\n    return layoutInfo;\n  }).then(function( layoutInfoUpdated ){\n    layoutInfo.layoutNodes = layoutInfoUpdated.layoutNodes; // get the positions\n\n    thread.stop();\n    done();\n  });\n\n  var done = function(){\n    refresh({ force: true });\n\n    // Layout has finished\n    layout.one('layoutstop', options.stop);\n    layout.trigger({ type: 'layoutstop', layout: layout });\n  };\n\n  return this; // chaining\n};\n\n\n/**\n * @brief : called on continuous layouts to stop them before they finish\n */\nCoseLayout.prototype.stop = function(){\n  this.stopped = true;\n\n  if( this.thread ){\n    this.thread.stop();\n  }\n\n  this.trigger('layoutstop');\n\n  return this; // chaining\n};\n\nCoseLayout.prototype.destroy = function(){\n  if( this.thread ){\n    this.thread.stop();\n  }\n\n  return this; // chaining\n};\n\n\n/**\n * @brief     : Creates an object which is contains all the data\n *              used in the layout process\n * @arg cy    : cytoscape.js object\n * @return    : layoutInfo object initialized\n */\nvar createLayoutInfo = function(cy, layout, options) {\n  // Shortcut\n  var edges = options.eles.edges();\n  var nodes = options.eles.nodes();\n\n  var layoutInfo   = {\n    isCompound   : cy.hasCompoundNodes(),\n    layoutNodes  : [],\n    idToIndex    : {},\n    nodeSize     : nodes.size(),\n    graphSet     : [],\n    indexToGraph : [],\n    layoutEdges  : [],\n    edgeSize     : edges.size(),\n    temperature  : options.initialTemp,\n    clientWidth  : cy.width(),\n    clientHeight : cy.width(),\n    boundingBox  : math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n                     x1: 0, y1: 0, w: cy.width(), h: cy.height()\n                   } )\n  };\n\n  var components = options.eles.components();\n  var id2cmptId = {};\n\n  for( var i = 0; i < components.length; i++ ){\n    var component = components[i];\n\n    for( var j = 0; j < component.length; j++ ){\n      var node = component[j];\n\n      id2cmptId[ node.id() ] = i;\n    }\n  }\n\n  // Iterate over all nodes, creating layout nodes\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = nodes[i];\n    var nbb = n.boundingBox();\n\n    var tempNode        = {};\n    tempNode.isLocked   = n.locked();\n    tempNode.id         = n.data('id');\n    tempNode.parentId   = n.data('parent');\n    tempNode.cmptId     = id2cmptId[ n.id() ];\n    tempNode.children   = [];\n    tempNode.positionX  = n.position('x');\n    tempNode.positionY  = n.position('y');\n    tempNode.offsetX    = 0;\n    tempNode.offsetY    = 0;\n    tempNode.height     = nbb.w;\n    tempNode.width      = nbb.h;\n    tempNode.maxX       = tempNode.positionX + tempNode.width  / 2;\n    tempNode.minX       = tempNode.positionX - tempNode.width  / 2;\n    tempNode.maxY       = tempNode.positionY + tempNode.height / 2;\n    tempNode.minY       = tempNode.positionY - tempNode.height / 2;\n    tempNode.padLeft    = parseFloat( n.style('padding-left') );\n    tempNode.padRight   = parseFloat( n.style('padding-right') );\n    tempNode.padTop     = parseFloat( n.style('padding-top') );\n    tempNode.padBottom  = parseFloat( n.style('padding-bottom') );\n\n    // forces\n    tempNode.nodeRepulsion = is.fn( options.nodeRepulsion ) ? options.nodeRepulsion.call( n, n ) : options.nodeRepulsion;\n\n    // Add new node\n    layoutInfo.layoutNodes.push(tempNode);\n    // Add entry to id-index map\n    layoutInfo.idToIndex[tempNode.id] = i;\n  }\n\n  // Inline implementation of a queue, used for traversing the graph in BFS order\n  var queue = [];\n  var start = 0;   // Points to the start the queue\n  var end   = -1;  // Points to the end of the queue\n\n  var tempGraph = [];\n\n  // Second pass to add child information and\n  // initialize queue for hierarchical traversal\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = layoutInfo.layoutNodes[i];\n    var p_id = n.parentId;\n    // Check if node n has a parent node\n    if (null != p_id) {\n    // Add node Id to parent's list of children\n    layoutInfo.layoutNodes[layoutInfo.idToIndex[p_id]].children.push(n.id);\n    } else {\n    // If a node doesn't have a parent, then it's in the root graph\n    queue[++end] = n.id;\n    tempGraph.push(n.id);\n    }\n  }\n\n  // Add root graph to graphSet\n  layoutInfo.graphSet.push(tempGraph);\n\n  // Traverse the graph, level by level,\n  while (start <= end) {\n    // Get the node to visit and remove it from queue\n    var node_id  = queue[start++];\n    var node_ix  = layoutInfo.idToIndex[node_id];\n    var node     = layoutInfo.layoutNodes[node_ix];\n    var children = node.children;\n    if (children.length > 0) {\n    // Add children nodes as a new graph to graph set\n    layoutInfo.graphSet.push(children);\n    // Add children to que queue to be visited\n    for (var i = 0; i < children.length; i++) {\n      queue[++end] = children[i];\n    }\n    }\n  }\n\n  // Create indexToGraph map\n  for (var i = 0; i < layoutInfo.graphSet.length; i++) {\n    var graph = layoutInfo.graphSet[i];\n    for (var j = 0; j < graph.length; j++) {\n    var index = layoutInfo.idToIndex[graph[j]];\n    layoutInfo.indexToGraph[index] = i;\n    }\n  }\n\n  // Iterate over all edges, creating Layout Edges\n  for (var i = 0; i < layoutInfo.edgeSize; i++) {\n    var e = edges[i];\n    var tempEdge = {};\n    tempEdge.id       = e.data('id');\n    tempEdge.sourceId = e.data('source');\n    tempEdge.targetId = e.data('target');\n\n    // Compute ideal length\n    var idealLength = is.fn( options.idealEdgeLength ) ? options.idealEdgeLength.call( e, e ) : options.idealEdgeLength;\n    var elasticity = is.fn( options.edgeElasticity ) ? options.edgeElasticity.call( e, e ) : options.edgeElasticity;\n\n    // Check if it's an inter graph edge\n    var sourceIx    = layoutInfo.idToIndex[tempEdge.sourceId];\n    var targetIx    = layoutInfo.idToIndex[tempEdge.targetId];\n    var sourceGraph = layoutInfo.indexToGraph[sourceIx];\n    var targetGraph = layoutInfo.indexToGraph[targetIx];\n\n    if (sourceGraph != targetGraph) {\n      // Find lowest common graph ancestor\n      var lca = findLCA(tempEdge.sourceId, tempEdge.targetId, layoutInfo);\n\n      // Compute sum of node depths, relative to lca graph\n      var lcaGraph = layoutInfo.graphSet[lca];\n      var depth    = 0;\n\n      // Source depth\n      var tempNode = layoutInfo.layoutNodes[sourceIx];\n      while ( -1 === lcaGraph.indexOf(tempNode.id) ) {\n        tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n        depth++;\n      }\n\n      // Target depth\n      tempNode = layoutInfo.layoutNodes[targetIx];\n      while ( -1 === lcaGraph.indexOf(tempNode.id) ) {\n        tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n        depth++;\n      }\n\n      // logDebug('LCA of nodes ' + tempEdge.sourceId + ' and ' + tempEdge.targetId +\n        //  \". Index: \" + lca + \" Contents: \" + lcaGraph.toString() +\n        //  \". Depth: \" + depth);\n\n      // Update idealLength\n      idealLength *= depth * options.nestingFactor;\n    }\n\n    tempEdge.idealLength = idealLength;\n    tempEdge.elasticity = elasticity;\n\n    layoutInfo.layoutEdges.push(tempEdge);\n  }\n\n  // Finally, return layoutInfo object\n  return layoutInfo;\n};\n\n\n/**\n * @brief : This function finds the index of the lowest common\n *          graph ancestor between 2 nodes in the subtree\n *          (from the graph hierarchy induced tree) whose\n *          root is graphIx\n *\n * @arg node1: node1's ID\n * @arg node2: node2's ID\n * @arg layoutInfo: layoutInfo object\n *\n */\nvar findLCA = function(node1, node2, layoutInfo) {\n  // Find their common ancester, starting from the root graph\n  var res = findLCA_aux(node1, node2, 0, layoutInfo);\n  if (2 > res.count) {\n    // If aux function couldn't find the common ancester,\n    // then it is the root graph\n    return 0;\n  } else {\n    return res.graph;\n  }\n};\n\n\n/**\n * @brief          : Auxiliary function used for LCA computation\n *\n * @arg node1      : node1's ID\n * @arg node2      : node2's ID\n * @arg graphIx    : subgraph index\n * @arg layoutInfo : layoutInfo object\n *\n * @return         : object of the form {count: X, graph: Y}, where:\n *                   X is the number of ancesters (max: 2) found in\n *                   graphIx (and it's subgraphs),\n *                   Y is the graph index of the lowest graph containing\n *                   all X nodes\n */\nvar findLCA_aux = function(node1, node2, graphIx, layoutInfo) {\n  var graph = layoutInfo.graphSet[graphIx];\n  // If both nodes belongs to graphIx\n  if (-1 < graph.indexOf(node1) && -1 < graph.indexOf(node2)) {\n    return {count:2, graph:graphIx};\n  }\n\n  // Make recursive calls for all subgraphs\n  var c = 0;\n  for (var i = 0; i < graph.length; i++) {\n    var nodeId   = graph[i];\n    var nodeIx   = layoutInfo.idToIndex[nodeId];\n    var children = layoutInfo.layoutNodes[nodeIx].children;\n\n    // If the node has no child, skip it\n    if (0 === children.length) {\n    continue;\n    }\n\n    var childGraphIx = layoutInfo.indexToGraph[layoutInfo.idToIndex[children[0]]];\n    var result = findLCA_aux(node1, node2, childGraphIx, layoutInfo);\n    if (0 === result.count) {\n    // Neither node1 nor node2 are present in this subgraph\n    continue;\n    } else if (1 === result.count) {\n    // One of (node1, node2) is present in this subgraph\n    c++;\n    if (2 === c) {\n      // We've already found both nodes, no need to keep searching\n      break;\n    }\n    } else {\n    // Both nodes are present in this subgraph\n    return result;\n    }\n  }\n\n  return {count:c, graph:graphIx};\n};\n\n\n/**\n * @brief: printsLayoutInfo into js console\n *         Only used for debbuging\n */\nvar printLayoutInfo = function(layoutInfo) {\n  /* jshint ignore:start */\n\n  if (!DEBUG) {\n    return;\n  }\n  console.debug(\"layoutNodes:\");\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = layoutInfo.layoutNodes[i];\n    var s =\n    \"\\nindex: \"     + i +\n    \"\\nId: \"        + n.id +\n    \"\\nChildren: \"  + n.children.toString() +\n    \"\\nparentId: \"  + n.parentId  +\n    \"\\npositionX: \" + n.positionX +\n    \"\\npositionY: \" + n.positionY +\n    \"\\nOffsetX: \" + n.offsetX +\n    \"\\nOffsetY: \" + n.offsetY +\n    \"\\npadLeft: \" + n.padLeft +\n    \"\\npadRight: \" + n.padRight +\n    \"\\npadTop: \" + n.padTop +\n    \"\\npadBottom: \" + n.padBottom;\n\n    console.debug(s);\n  }\n\n  console.debug('idToIndex');\n  for (var i in layoutInfo.idToIndex) {\n    console.debug(\"Id: \" + i + \"\\nIndex: \" + layoutInfo.idToIndex[i]);\n  }\n\n  console.debug('Graph Set');\n  var set = layoutInfo.graphSet;\n  for (var i = 0; i < set.length; i ++) {\n    console.debug(\"Set : \" + i + \": \" + set[i].toString());\n  }\n\n  var s = 'IndexToGraph';\n  for (var i = 0; i < layoutInfo.indexToGraph.length; i ++) {\n    s += \"\\nIndex : \" + i + \" Graph: \"+ layoutInfo.indexToGraph[i];\n  }\n  console.debug(s);\n\n  s = 'Layout Edges';\n  for (var i = 0; i < layoutInfo.layoutEdges.length; i++) {\n    var e = layoutInfo.layoutEdges[i];\n    s += \"\\nEdge Index: \" + i + \" ID: \" + e.id +\n    \" SouceID: \" + e.sourceId + \" TargetId: \" + e.targetId +\n    \" Ideal Length: \" + e.idealLength;\n  }\n  console.debug(s);\n\n  s =  \"nodeSize: \" + layoutInfo.nodeSize;\n  s += \"\\nedgeSize: \" + layoutInfo.edgeSize;\n  s += \"\\ntemperature: \" + layoutInfo.temperature;\n  console.debug(s);\n\n  return;\n  /* jshint ignore:end */\n};\n\n\n/**\n * @brief : Randomizes the position of all nodes\n */\nvar randomizePositions = function(layoutInfo, cy) {\n  var width     = layoutInfo.clientWidth;\n  var height    = layoutInfo.clientHeight;\n\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = layoutInfo.layoutNodes[i];\n\n    // No need to randomize compound nodes or locked nodes\n    if ( 0 === n.children.length && !n.isLocked ) {\n      n.positionX = Math.random() * width;\n      n.positionY = Math.random() * height;\n    }\n  }\n};\n\n\n/**\n * @brief          : Updates the positions of nodes in the network\n * @arg layoutInfo : LayoutInfo object\n * @arg cy         : Cytoscape object\n * @arg options    : Layout options\n */\nvar refreshPositions = function(layoutInfo, cy, options) {\n  // var s = 'Refreshing positions';\n  // logDebug(s);\n\n  var layout = options.layout;\n  var nodes = options.eles.nodes();\n  var bb = layoutInfo.boundingBox;\n  var coseBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity };\n\n  if( options.boundingBox ){\n    nodes.forEach(function( node ){\n      var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]];\n\n      coseBB.x1 = Math.min( coseBB.x1, lnode.positionX );\n      coseBB.x2 = Math.max( coseBB.x2, lnode.positionX );\n\n      coseBB.y1 = Math.min( coseBB.y1, lnode.positionY );\n      coseBB.y2 = Math.max( coseBB.y2, lnode.positionY );\n    });\n\n    coseBB.w = coseBB.x2 - coseBB.x1;\n    coseBB.h = coseBB.y2 - coseBB.y1;\n  }\n\n  nodes.positions(function(i, ele) {\n    var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[ele.data('id')]];\n    // s = \"Node: \" + lnode.id + \". Refreshed position: (\" +\n    // lnode.positionX + \", \" + lnode.positionY + \").\";\n    // logDebug(s);\n\n    if( options.boundingBox ){ // then add extra bounding box constraint\n      var pctX = (lnode.positionX - coseBB.x1) / coseBB.w;\n      var pctY = (lnode.positionY - coseBB.y1) / coseBB.h;\n\n      return {\n        x: bb.x1 + pctX * bb.w,\n        y: bb.y1 + pctY * bb.h\n      };\n    } else {\n      return {\n        x: lnode.positionX,\n        y: lnode.positionY\n      };\n    }\n  });\n\n  // Trigger layoutReady only on first call\n  if (true !== layoutInfo.ready) {\n    // s = 'Triggering layoutready';\n    // logDebug(s);\n    layoutInfo.ready = true;\n    layout.one('layoutready', options.ready);\n    layout.trigger({ type: 'layoutready', layout: this });\n  }\n};\n\n/**\n * @brief : Logs a debug message in JS console, if DEBUG is ON\n */\n// var logDebug = function(text) {\n//   if (DEBUG) {\n//     console.debug(text);\n//   }\n// };\n\nmodule.exports = CoseLayout;\n\n},{\"../../is\":77,\"../../math\":79,\"../../thread\":92,\"../../util\":94}],49:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\nvar math = _dereq_('../../math');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  padding: 30, // padding used on fit\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n  avoidOverlapPadding: 10, // extra spacing around nodes when avoidOverlap: true\n  condense: false, // uses all available space on false, uses minimal space on true\n  rows: undefined, // force num of rows in the grid\n  cols: undefined, // force num of columns in the grid\n  position: function( node ){}, // returns { row, col } for element\n  sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction GridLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nGridLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var cy = params.cy;\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n\n  if( options.sort ){\n    nodes = nodes.sort( options.sort );\n  }\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  if( bb.h === 0 || bb.w === 0){\n    nodes.layoutPositions(this, options, function(){\n      return { x: bb.x1, y: bb.y1 };\n    });\n\n  } else {\n\n    // width/height * splits^2 = cells where splits is number of times to split width\n    var cells = nodes.size();\n    var splits = Math.sqrt( cells * bb.h/bb.w );\n    var rows = Math.round( splits );\n    var cols = Math.round( bb.w/bb.h * splits );\n\n    var small = function(val){\n      if( val == null ){\n        return Math.min(rows, cols);\n      } else {\n        var min = Math.min(rows, cols);\n        if( min == rows ){\n          rows = val;\n        } else {\n          cols = val;\n        }\n      }\n    };\n\n    var large = function(val){\n      if( val == null ){\n        return Math.max(rows, cols);\n      } else {\n        var max = Math.max(rows, cols);\n        if( max == rows ){\n          rows = val;\n        } else {\n          cols = val;\n        }\n      }\n    };\n\n    var oRows = options.rows;\n    var oCols = options.cols != null ? options.cols : options.columns;\n\n    // if rows or columns were set in options, use those values\n    if( oRows != null && oCols != null ){\n      rows = oRows;\n      cols = oCols;\n    } else if( oRows != null && oCols == null ){\n      rows = oRows;\n      cols = Math.ceil( cells / rows );\n    } else if( oRows == null && oCols != null ){\n      cols = oCols;\n      rows = Math.ceil( cells / cols );\n    }\n\n    // otherwise use the automatic values and adjust accordingly\n\n    // if rounding was up, see if we can reduce rows or columns\n    else if( cols * rows > cells ){\n      var sm = small();\n      var lg = large();\n\n      // reducing the small side takes away the most cells, so try it first\n      if( (sm - 1) * lg >= cells ){\n        small(sm - 1);\n      } else if( (lg - 1) * sm >= cells ){\n        large(lg - 1);\n      }\n    } else {\n\n      // if rounding was too low, add rows or columns\n      while( cols * rows < cells ){\n        var sm = small();\n        var lg = large();\n\n        // try to add to larger side first (adds less in multiplication)\n        if( (lg + 1) * sm >= cells ){\n          large(lg + 1);\n        } else {\n          small(sm + 1);\n        }\n      }\n    }\n\n    var cellWidth = bb.w / cols;\n    var cellHeight = bb.h / rows;\n\n    if( options.condense ){\n      cellWidth = 0;\n      cellHeight = 0;\n    }\n\n    if( options.avoidOverlap ){\n      for( var i = 0; i < nodes.length; i++ ){\n        var node = nodes[i];\n        var pos = node._private.position;\n\n        if( pos.x == null || pos.y == null ){ // for bb\n          pos.x = 0;\n          pos.y = 0;\n        }\n\n        var nbb = node.boundingBox();\n        var p = options.avoidOverlapPadding;\n\n        var w = nbb.w + p;\n        var h = nbb.h + p;\n\n        cellWidth = Math.max( cellWidth, w );\n        cellHeight = Math.max( cellHeight, h );\n      }\n    }\n\n    var cellUsed = {}; // e.g. 'c-0-2' => true\n\n    var used = function(row, col){\n      return cellUsed['c-' + row + '-' + col] ? true : false;\n    };\n\n    var use = function(row, col){\n      cellUsed['c-' + row + '-' + col] = true;\n    };\n\n    // to keep track of current cell position\n    var row = 0;\n    var col = 0;\n    var moveToNextCell = function(){\n      col++;\n      if( col >= cols ){\n        col = 0;\n        row++;\n      }\n    };\n\n    // get a cache of all the manual positions\n    var id2manPos = {};\n    for( var i = 0; i < nodes.length; i++ ){\n      var node = nodes[i];\n      var rcPos = options.position( node );\n\n      if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd\n        var pos = {\n          row: rcPos.row,\n          col: rcPos.col\n        };\n\n        if( pos.col === undefined ){ // find unused col\n          pos.col = 0;\n\n          while( used(pos.row, pos.col) ){\n            pos.col++;\n          }\n        } else if( pos.row === undefined ){ // find unused row\n          pos.row = 0;\n\n          while( used(pos.row, pos.col) ){\n            pos.row++;\n          }\n        }\n\n        id2manPos[ node.id() ] = pos;\n        use( pos.row, pos.col );\n      }\n    }\n\n    var getPos = function(i, element){\n      var x, y;\n\n      if( element.locked() || element.isFullAutoParent() ){\n        return false;\n      }\n\n      // see if we have a manual position set\n      var rcPos = id2manPos[ element.id() ];\n      if( rcPos ){\n        x = rcPos.col * cellWidth + cellWidth/2 + bb.x1;\n        y = rcPos.row * cellHeight + cellHeight/2 + bb.y1;\n\n      } else { // otherwise set automatically\n\n        while( used(row, col) ){\n          moveToNextCell();\n        }\n\n        x = col * cellWidth + cellWidth/2 + bb.x1;\n        y = row * cellHeight + cellHeight/2 + bb.y1;\n        use( row, col );\n\n        moveToNextCell();\n      }\n\n      return { x: x, y: y };\n\n    };\n\n    nodes.layoutPositions( this, options, getPos );\n  }\n\n  return this; // chaining\n\n};\n\nmodule.exports = GridLayout;\n\n},{\"../../math\":79,\"../../util\":94}],50:[function(_dereq_,module,exports){\n'use strict';\n\nmodule.exports = [\n  { name: 'breadthfirst', impl: _dereq_('./breadthfirst') },\n  { name: 'circle', impl: _dereq_('./circle') },\n  { name: 'concentric',impl: _dereq_('./concentric') },\n  { name: 'cose', impl: _dereq_('./cose') },\n  { name: 'grid', impl: _dereq_('./grid') },\n  { name: 'null', impl: _dereq_('./null') },\n  { name: 'preset', impl: _dereq_('./preset') },\n  { name: 'random', impl: _dereq_('./random') }\n];\n\n},{\"./breadthfirst\":45,\"./circle\":46,\"./concentric\":47,\"./cose\":48,\"./grid\":49,\"./null\":51,\"./preset\":52,\"./random\":53}],51:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\n\n// default layout options\nvar defaults = {\n  ready: function(){}, // on layoutready\n  stop: function(){} // on layoutstop\n};\n\n// constructor\n// options : object containing layout options\nfunction NullLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\n// runs the layout\nNullLayout.prototype.run = function(){\n  var options = this.options;\n  var eles = options.eles; // elements to consider in the layout\n  var layout = this;\n\n  // cy is automatically populated for us in the constructor\n  var cy = options.cy; // jshint ignore:line\n\n  layout.trigger('layoutstart');\n\n  // puts all nodes at (0, 0)\n  eles.nodes().positions(function(){\n    return {\n      x: 0,\n      y: 0\n    };\n  });\n\n  // trigger layoutready when each node has had its position set at least once\n  layout.one('layoutready', options.ready);\n  layout.trigger('layoutready');\n\n  // trigger layoutstop when the layout stops (e.g. finishes)\n  layout.one('layoutstop', options.stop);\n  layout.trigger('layoutstop');\n\n  return this; // chaining\n};\n\n// called on continuous layouts to stop them before they finish\nNullLayout.prototype.stop = function(){\n  return this; // chaining\n};\n\nmodule.exports = NullLayout;\n\n},{\"../../util\":94}],52:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\nvar is = _dereq_('../../is');\n\nvar defaults = {\n  positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; }\n  zoom: undefined, // the zoom level to set (prob want fit = false if set)\n  pan: undefined, // the pan level to set (prob want fit = false if set)\n  fit: true, // whether to fit to viewport\n  padding: 30, // padding on fit\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction PresetLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nPresetLayout.prototype.run = function(){\n  var options = this.options;\n  var eles = options.eles;\n\n  var nodes = eles.nodes();\n  var posIsFn = is.fn( options.positions );\n\n  function getPosition(node){\n    if( options.positions == null ){\n      return null;\n    }\n\n    if( posIsFn ){\n      return options.positions.apply( node, [ node ] );\n    }\n\n    var pos = options.positions[node._private.data.id];\n\n    if( pos == null ){\n      return null;\n    }\n\n    return pos;\n  }\n\n  nodes.layoutPositions(this, options, function(i, node){\n    var position = getPosition(node);\n\n    if( node.locked() || position == null ){\n      return false;\n    }\n\n    return position;\n  });\n\n  return this; // chaining\n};\n\nmodule.exports = PresetLayout;\n\n},{\"../../is\":77,\"../../util\":94}],53:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../util');\nvar math = _dereq_('../../math');\n\nvar defaults = {\n  fit: true, // whether to fit to viewport\n  padding: 30, // fit padding\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction RandomLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nRandomLayout.prototype.run = function(){\n  var options = this.options;\n  var cy = options.cy;\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var getPos = function( i, node ){\n    return {\n      x: bb.x1 + Math.round( Math.random() * bb.w ),\n      y: bb.y1 + Math.round( Math.random() * bb.h )\n    };\n  };\n\n  nodes.layoutPositions( this, options, getPos );\n\n  return this; // chaining\n};\n\nmodule.exports = RandomLayout;\n\n},{\"../../math\":79,\"../../util\":94}],54:[function(_dereq_,module,exports){\n'use strict';\n\nvar math = _dereq_('../../../math');\nvar is = _dereq_('../../../is');\nvar util = _dereq_('../../../util');\n\nvar BRp = {};\n\nBRp.arrowShapeHeight = 0.3;\n\nBRp.registerArrowShapes = function(){\n  var arrowShapes = this.arrowShapes = {};\n  var renderer = this;\n\n  // Contract for arrow shapes:\n  // 0, 0 is arrow tip\n  // (0, 1) is direction towards node\n  // (1, 0) is right\n  //\n  // functional api:\n  // collide: check x, y in shape\n  // roughCollide: called before collide, no false negatives\n  // draw: draw\n  // spacing: dist(arrowTip, nodeBoundary)\n  // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip\n\n  var bbCollide = function( x, y, size, angle, translation, padding ){\n    var x1 = translation.x - size/2 - padding;\n    var x2 = translation.x + size/2 + padding;\n    var y1 = translation.y - size/2 - padding;\n    var y2 = translation.y + size/2 + padding;\n\n    var inside = (x1 <= x && x <= x2) && (y1 <= y && y <= y2);\n\n    return inside;\n  };\n\n  var transform = function( x, y, size, angle, translation ){\n    var xRotated = x * Math.cos(angle) - y * Math.sin(angle);\n    var yRotated = x * Math.sin(angle) + y * Math.cos(angle);\n\n    var xScaled = xRotated * size;\n    var yScaled = yRotated * size;\n\n    var xTranslated = xScaled + translation.x;\n    var yTranslated = yScaled + translation.y;\n\n    return {\n      x: xTranslated,\n      y: yTranslated\n    };\n  };\n\n  var transformPoints = function( pts, size, angle, translation ){\n    var retPts = [];\n\n    for( var i = 0; i < pts.length; i += 2 ){\n      var x = pts[i];\n      var y = pts[i + 1];\n\n      retPts.push( transform(x, y, size, angle, translation) );\n    }\n\n    return retPts;\n  };\n\n  var pointsToArr = function( pts ){\n    var ret = [];\n\n    for( var i = 0; i < pts.length; i++ ){\n      var p = pts[i];\n\n      ret.push( p.x, p.y );\n    }\n\n    return ret;\n  };\n\n  var defineArrowShape = function( name, defn ){\n    if( is.string(defn) ){\n      defn = arrowShapes[ defn ];\n    }\n\n    arrowShapes[ name ] = util.extend( {\n      name: name,\n\n      points: [\n        -0.15, -0.3,\n        0.15, -0.3,\n        0.15, 0.3,\n        -0.15, 0.3\n      ],\n\n      collide: function( x, y, size, angle, translation, padding ){\n        var points = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );\n        var inside = math.pointInsidePolygonPoints( x, y, points );\n\n        return inside;\n      },\n\n      roughCollide: bbCollide,\n\n      draw: function( context, size, angle, translation ){\n        var points = transformPoints( this.points, size, angle, translation );\n\n        renderer.arrowShapeImpl('polygon')( context, points );\n      },\n\n      spacing: function( edge ){\n        return 0;\n      },\n\n      gap: function( edge ){\n        return edge._private.style['width'].pfValue * 2;\n      }\n    }, defn );\n  };\n\n  defineArrowShape( 'none', {\n    collide: util.falsify,\n\n    roughCollide: util.falsify,\n\n    draw: util.noop,\n\n    spacing: util.zeroify,\n\n    gap: util.zeroify\n  } );\n\n  defineArrowShape( 'triangle', {\n    points: [\n      -0.15, -0.3,\n      0, 0,\n      0.15, -0.3\n    ]\n  } );\n\n  defineArrowShape( 'arrow', 'triangle' );\n\n  defineArrowShape( 'triangle-backcurve', {\n    points: arrowShapes['triangle'].points,\n\n    controlPoint: [ 0, -0.15 ],\n\n    roughCollide: bbCollide,\n\n    draw: function( context, size, angle, translation ){\n      var ptsTrans = transformPoints( this.points, size, angle, translation );\n      var ctrlPt = this.controlPoint;\n      var ctrlPtTrans = transform( ctrlPt[0], ctrlPt[1], size, angle, translation );\n\n      renderer.arrowShapeImpl( this.name )( context, ptsTrans, ctrlPtTrans );\n    },\n\n    gap: function( edge ){\n      return edge._private.style['width'].pfValue;\n    }\n  } );\n\n\n  defineArrowShape( 'triangle-tee', {\n    points: [\n      -0.15, -0.3,\n      0, 0,\n      0.15, -0.3,\n      -0.15, -0.3\n    ],\n\n    pointsTee: [\n      -0.15, -0.4,\n      -0.15, -0.5,\n      0.15, -0.5,\n      0.15, -0.4\n    ],\n\n    collide: function( x, y, size, angle, translation, padding ){\n      var triPts = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );\n      var teePts = pointsToArr( transformPoints( this.pointsTee, size + 2*padding, angle, translation ) );\n\n      var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts );\n\n      return inside;\n    },\n\n    draw: function( context, size, angle, translation ){\n      var triPts = transformPoints( this.points, size, angle, translation );\n      var teePts = transformPoints( this.pointsTee, size, angle, translation );\n\n      renderer.arrowShapeImpl( this.name )( context, triPts, teePts );\n    }\n  } );\n\n  defineArrowShape( 'vee', {\n    points: [\n      -0.15, -0.3,\n      0, 0,\n      0.15, -0.3,\n      0, -0.15\n    ],\n\n    gap: function( edge ){\n      return edge._private.style['width'].pfValue;\n    }\n  } );\n\n  defineArrowShape( 'half-triangle-overshot', {\n    points: [\n      0, -0.25,\n      -0.5, -0.25,\n      0.5, 0.25\n    ],\n\n    leavePathOpen: true,\n\n    matchEdgeWidth: true\n  } );\n\n  defineArrowShape( 'circle', {\n    radius: 0.15,\n\n    collide: function( x, y, size, angle, translation, padding ){\n      var t = translation;\n      var inside = ( Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2*padding) * this.radius, 2) );\n\n      return inside;\n    },\n\n    draw: function( context, size, angle, translation ){\n      renderer.arrowShapeImpl( this.name )( context, translation.x, translation.y, this.radius * size );\n    },\n\n    spacing: function( edge ){\n      return renderer.getArrowWidth(edge._private.style['width'].pfValue)\n        * this.radius;\n    }\n  } );\n\n  defineArrowShape( 'inhibitor', {\n    points: [\n      -0.25, 0,\n      -0.25, -0.1,\n      0.25, -0.1,\n      0.25, 0\n    ],\n\n    spacing: function( edge ){\n      return 1;\n    },\n\n    gap: function( edge ){\n      return 1;\n    }\n  } );\n\n  defineArrowShape( 'tee', 'inhibitor' );\n\n  defineArrowShape( 'square', {\n    points: [\n      -0.15, 0.00,\n      0.15, 0.00,\n      0.15, -0.3,\n      -0.15, -0.3\n    ]\n  } );\n\n  defineArrowShape( 'diamond', {\n    points: [\n      -0.15, -0.15,\n      0, -0.3,\n      0.15, -0.15,\n      0, 0\n    ],\n\n    gap: function( edge ){\n      return edge._private.style['width'].pfValue;\n    }\n  } );\n\n};\n\nmodule.exports = BRp;\n\n},{\"../../../is\":77,\"../../../math\":79,\"../../../util\":94}],55:[function(_dereq_,module,exports){\n'use strict';\n\nvar BRp = {};\n\nvar delEleCache = function( r ){\n  r.eleEache = null;\n};\n\nvar getEleCache = function( r ){\n  if( !r.eleEache ){\n    r.eleEache = {\n      nodes: r.cy.nodes(),\n      edges: r.cy.edges()\n    };\n  }\n\n  return r.eleEache;\n};\n\nBRp.getCachedElements = function(){\n  return getEleCache( this );\n};\n\nBRp.getCachedNodes = function(){\n  return getEleCache( this ).nodes;\n};\n\nBRp.getCachedEdges = function(){\n  return getEleCache( this ).edges;\n};\n\nBRp.updateElementsCache = function(){\n  var r = this;\n\n  delEleCache( r );\n\n  return getEleCache( r );\n};\n\nmodule.exports = BRp;\n\n},{}],56:[function(_dereq_,module,exports){\n'use strict';\n\nvar math = _dereq_('../../../math');\nvar is = _dereq_('../../../is');\nvar zIndexSort = _dereq_('../../../collection/zsort');\n\nvar BRp = {};\n\n// Project mouse\nBRp.projectIntoViewport = function(clientX, clientY) {\n  var offsets = this.findContainerClientCoords();\n  var offsetLeft = offsets[0];\n  var offsetTop = offsets[1];\n\n  var x = clientX - offsetLeft;\n  var y = clientY - offsetTop;\n\n  x -= this.cy.pan().x; y -= this.cy.pan().y; x /= this.cy.zoom(); y /= this.cy.zoom();\n  return [x, y];\n};\n\nBRp.findContainerClientCoords = function() {\n  var container = this.container;\n\n  var bb = this.containerBB = this.containerBB || container.getBoundingClientRect();\n\n  return [bb.left, bb.top, bb.right - bb.left, bb.bottom - bb.top];\n};\n\nBRp.invalidateContainerClientCoordsCache = function(){\n  this.containerBB = null;\n};\n\n// Find nearest element\nBRp.findNearestElement = function(x, y, visibleElementsOnly, isTouch){\n  var self = this;\n  var r = this;\n  var eles = r.getCachedZSortedEles();\n  var near = [];\n  var zoom = r.cy.zoom();\n  var hasCompounds = r.cy.hasCompoundNodes();\n  var edgeThreshold = (isTouch ? 24 : 8) / zoom;\n  var nodeThreshold = (isTouch ? 8 : 2) / zoom;\n  var labelThreshold = (isTouch ? 8 : 2) / zoom;\n\n  function checkNode(node){\n    var _p = node._private;\n\n    if( _p.style['events'].strValue === 'no' ){ return; }\n\n    var width = node.outerWidth() + 2*nodeThreshold;\n    var height = node.outerHeight() + 2*nodeThreshold;\n    var hw = width/2;\n    var hh = height/2;\n    var pos = _p.position;\n\n    if(\n      pos.x - hw <= x && x <= pos.x + hw // bb check x\n        &&\n      pos.y - hh <= y && y <= pos.y + hh // bb check y\n    ){\n      var visible = !visibleElementsOnly || ( node.visible() && !node.transparent() );\n\n      // exit early if invisible edge and must be visible\n      if( visibleElementsOnly && !visible ){\n        return;\n      }\n\n      var shape = r.nodeShapes[ self.getNodeShape(node) ];\n\n      if(\n        shape.checkPoint(x, y, 0, width, height, pos.x, pos.y)\n      ){\n        near.push( node );\n      }\n\n    }\n  }\n\n  function checkEdge(edge){\n    var _p = edge._private;\n\n    if( _p.style['events'].strValue === 'no' ){ return; }\n\n    var rs = _p.rscratch;\n    var style = _p.style;\n    var width = style['width'].pfValue/2 + edgeThreshold; // more like a distance radius from centre\n    var widthSq = width * width;\n    var width2 = width * 2;\n    var src = _p.source;\n    var tgt = _p.target;\n    var inEdgeBB = false;\n    var sqDist;\n\n    // exit early if invisible edge and must be visible\n    var passedVisibilityCheck;\n    var passesVisibilityCheck = function(){\n      if( passedVisibilityCheck !== undefined ){\n        return passedVisibilityCheck;\n      }\n\n      if( !visibleElementsOnly ){\n        passedVisibilityCheck = true;\n        return true;\n      }\n\n      var visible = edge.visible() && !edge.transparent();\n      if( visible ){\n        passedVisibilityCheck = true;\n        return true;\n      }\n\n      passedVisibilityCheck = false;\n      return false;\n    };\n\n    if( rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack' ){\n      var pts = rs.allpts;\n\n      for( var i = 0; i + 3 < pts.length; i += 2 ){\n        if(\n          (inEdgeBB = math.inLineVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], width2))\n            && passesVisibilityCheck() &&\n          widthSq > ( sqDist = math.sqDistanceToFiniteLine(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3]) )\n        ){\n          near.push( edge );\n        }\n      }\n\n    } else if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n      var pts = rs.allpts;\n      for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){\n        if(\n          (inEdgeBB = math.inBezierVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5], width2))\n            && passesVisibilityCheck() &&\n          (widthSq > (sqDist = math.sqDistanceToQuadraticBezier(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5])) )\n        ){\n          near.push( edge );\n        }\n      }\n    }\n\n    // if we're close to the edge but didn't hit it, maybe we hit its arrows\n    if( inEdgeBB && passesVisibilityCheck() && near.length === 0 || near[near.length - 1] !== edge ){\n      var src = src || _p.source;\n      var tgt = tgt || _p.target;\n\n      var eWidth = style['width'].pfValue;\n      var arSize = self.getArrowWidth( eWidth );\n\n      var arrows = [\n        { name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle },\n        { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle },\n        { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle },\n        { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle }\n      ];\n\n      for( var i = 0; i < arrows.length; i++ ){\n        var ar = arrows[i];\n        var shape = r.arrowShapes[ style[ar.name+'-arrow-shape'].value ];\n\n        if(\n          shape.roughCollide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)\n           &&\n          shape.collide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)\n        ){\n          near.push( edge );\n          break;\n        }\n      }\n    }\n\n    // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence)\n    if( hasCompounds &&  near.length > 0 && near[ near.length - 1 ] === edge ){\n      checkNode( src );\n      checkNode( tgt );\n    }\n  }\n\n  function checkLabel(ele){\n    var _p = ele._private;\n    var th = labelThreshold;\n\n    if( _p.style['text-events'].strValue === 'no' ){ return; }\n\n    // adjust bb w/ angle\n    if( _p.group === 'edges' && _p.style['edge-text-rotation'].strValue === 'autorotate' ){\n\n      var rstyle = _p.rstyle;\n      var lw = rstyle.labelWidth + 2*th;\n      var lh = rstyle.labelHeight + 2*th;\n      var lx = rstyle.labelX;\n      var ly = rstyle.labelY;\n\n      var theta = _p.rscratch.labelAngle;\n      var cos = Math.cos( theta );\n      var sin = Math.sin( theta );\n\n      var rotate = function( x, y ){\n        x = x - lx;\n        y = y - ly;\n\n        return {\n          x: x*cos - y*sin + lx,\n          y: x*sin + y*cos + ly\n        };\n      };\n\n      var lx1 = lx - lw/2;\n      var lx2 = lx + lw/2;\n      var ly1 = ly - lh/2;\n      var ly2 = ly + lh/2;\n\n      var px1y1 = rotate( lx1, ly1 );\n      var px1y2 = rotate( lx1, ly2 );\n      var px2y1 = rotate( lx2, ly1 );\n      var px2y2 = rotate( lx2, ly2 );\n\n      var points = [\n        px1y1.x, px1y1.y,\n        px2y1.x, px2y1.y,\n        px2y2.x, px2y2.y,\n        px1y2.x, px1y2.y\n      ];\n\n      if( math.pointInsidePolygonPoints( x, y, points ) ){\n        near.push( ele );\n      }\n\n    } else {\n      var bb = ele.boundingBox({\n        includeLabels: true,\n        includeNodes: false,\n        includeEdges: false\n      });\n\n      // adjust bb w/ threshold\n      bb.x1 -= th;\n      bb.y1 -= th;\n      bb.x2 += th;\n      bb.y2 += th;\n      bb.w = bb.x2 - bb.x1;\n      bb.h = bb.y2 - bb.y1;\n\n      if( math.inBoundingBox( bb, x, y ) ){\n        near.push( ele );\n      }\n    }\n\n  }\n\n  for( var i = eles.length - 1; i >= 0; i-- ){ // reverse order for precedence\n    var ele = eles[i];\n    var _p = ele._private;\n\n    if( near.length > 0 ){ break; } // since we check in z-order, first found is top and best result => exit early\n\n    if( _p.group === 'nodes' ){\n      checkNode( ele );\n\n    } else  { // then edge\n      checkEdge( ele );\n    }\n\n    checkLabel( ele );\n\n  }\n\n\n  if( near.length > 0 ){\n    return near[ near.length - 1 ];\n  } else {\n    return null;\n  }\n};\n\n// 'Give me everything from this box'\nBRp.getAllInBox = function(x1, y1, x2, y2) {\n  var nodes = this.getCachedNodes();\n  var edges = this.getCachedEdges();\n  var box = [];\n\n  var x1c = Math.min(x1, x2);\n  var x2c = Math.max(x1, x2);\n  var y1c = Math.min(y1, y2);\n  var y2c = Math.max(y1, y2);\n\n  x1 = x1c;\n  x2 = x2c;\n  y1 = y1c;\n  y2 = y2c;\n\n  var boxBb = math.makeBoundingBox({\n    x1: x1, y1: y1,\n    x2: x2, y2: y2\n  });\n\n  for ( var i = 0; i < nodes.length; i++ ){\n    var node = nodes[i];\n    var nodeBb = node.boundingBox({\n      includeNodes: true,\n      includeEdges: false,\n      includeLabels: false\n    });\n\n    if( math.boundingBoxesIntersect(boxBb, nodeBb) ){\n      box.push(nodes[i]);\n    }\n  }\n\n  for( var e = 0; e < edges.length; e++ ){\n    var edge = edges[e];\n    var _p = edge._private;\n    var rs = _p.rscratch;\n\n    if( rs.startX != null && rs.startY != null && !math.inBoundingBox( boxBb, rs.startX, rs.startY ) ){ continue; }\n    if( rs.endX != null && rs.endY != null && !math.inBoundingBox( boxBb, rs.endX, rs.endY ) ){ continue; }\n\n    if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack' ){\n\n      var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts;\n      var allInside = true;\n\n      for( var i = 0; i < pts.length; i++ ){\n        if( !math.pointInBoundingBox( boxBb, pts[i] ) ){\n          allInside = false;\n          break;\n        }\n      }\n\n      if( allInside ){\n        box.push( edge );\n      }\n\n    } else if( rs.edgeType === 'haystack' || rs.edgeType === 'straight' ){\n      box.push( edge );\n    }\n\n  }\n\n  return box;\n};\n\n\n/**\n * Returns the shape of the given node. If the height or width of the given node\n * is set to auto, the node is considered to be a compound.\n *\n * @param node          a node\n * @return {String}     shape of the node\n */\nBRp.getNodeShape = function( node ){\n  var r = this;\n  var style = node._private.style;\n  var shape = style['shape'].value;\n\n  if( node.isParent() ){\n    if( shape === 'rectangle' || shape === 'roundrectangle' ){\n      return shape;\n    } else {\n      return 'rectangle';\n    }\n  }\n\n  if( shape === 'polygon' ){\n    var points = style['shape-polygon-points'].value;\n\n    return r.nodeShapes.makePolygon( points ).name;\n  }\n\n  return shape;\n};\n\nBRp.updateCachedZSortedEles = function(){\n  this.getCachedZSortedEles( true );\n};\n\nBRp.getCachedZSortedEles = function( forceRecalc ){\n  var lastNodes = this.lastZOrderCachedNodes;\n  var lastEdges = this.lastZOrderCachedEdges;\n  var nodes = this.getCachedNodes();\n  var edges = this.getCachedEdges();\n  var eles = [];\n\n  if( forceRecalc || !lastNodes || !lastEdges || lastNodes !== nodes || lastEdges !== edges ){\n    //console.time('cachezorder')\n\n    for( var i = 0; i < nodes.length; i++ ){\n      var n = nodes[i];\n\n      if( n.animated() || (n.visible() && !n.transparent()) ){\n        eles.push( n );\n      }\n    }\n\n    for( var i = 0; i < edges.length; i++ ){\n      var e = edges[i];\n\n      if( e.animated() || (e.visible() && !e.transparent()) ){\n        eles.push( e );\n      }\n    }\n\n    eles.sort( zIndexSort );\n    this.cachedZSortedEles = eles;\n    //console.log('make cache')\n\n    //console.timeEnd('cachezorder')\n  } else {\n    eles = this.cachedZSortedEles;\n    //console.log('read cache')\n  }\n\n  this.lastZOrderCachedNodes = nodes;\n  this.lastZOrderCachedEdges = edges;\n\n  return eles;\n};\n\nfunction pushBezierPts(edge, pts){\n  var qbezierAt = function( p1, p2, p3, t ){ return math.qbezierAt(p1, p2, p3, t); };\n  var _p = edge._private;\n  var bpts = _p.rstyle.bezierPts;\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.05 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.05 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.25 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.25 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.4 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.4 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.5 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.5 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.6 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.6 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.75 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.75 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.95 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.95 )\n  });\n}\n\nBRp.projectLines = function( edge ){\n  var _p = edge._private;\n  var rs = _p.rscratch;\n  var et = rs.edgeType;\n\n  if( et === 'multibezier' ||  et === 'bezier' ||  et === 'self' ||  et === 'compound' ){\n    var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line\n\n    for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){\n      pushBezierPts( edge, rs.allpts.slice(i, i+6) );\n    }\n  } else if(  et === 'segments' ){\n    var lpts = _p.rstyle.linePts = [];\n\n    for( var i = 0; i + 1 < rs.allpts.length; i += 2 ){\n      lpts.push({\n        x: rs.allpts[i],\n        y: rs.allpts[i+1]\n      });\n    }\n  } else if( et === 'haystack' ){\n    var hpts = rs.haystackPts;\n\n    _p.rstyle.haystackPts = [\n      { x: hpts[0], y: hpts[1] },\n      { x: hpts[2], y: hpts[3] }\n    ];\n  }\n};\n\nBRp.projectBezier = BRp.projectLines;\n\nBRp.recalculateNodeLabelProjection = function( node ){\n  var content = node._private.style['label'].strValue;\n  if( !content || content.match(/^\\s+$/) ){ return; }\n\n  var textX, textY;\n  var nodeWidth = node.outerWidth();\n  var nodeHeight = node.outerHeight();\n  var nodePos = node._private.position;\n  var textHalign = node._private.style['text-halign'].strValue;\n  var textValign = node._private.style['text-valign'].strValue;\n  var rs = node._private.rscratch;\n  var rstyle = node._private.rstyle;\n\n  switch( textHalign ){\n    case 'left':\n      textX = nodePos.x - nodeWidth / 2;\n      break;\n\n    case 'right':\n      textX = nodePos.x + nodeWidth / 2;\n      break;\n\n    default: // e.g. center\n      textX = nodePos.x;\n  }\n\n  switch( textValign ){\n    case 'top':\n      textY = nodePos.y - nodeHeight / 2;\n      break;\n\n    case 'bottom':\n      textY = nodePos.y + nodeHeight / 2;\n      break;\n\n    default: // e.g. middle\n      textY = nodePos.y;\n  }\n\n  rs.labelX = textX;\n  rs.labelY = textY;\n  rstyle.labelX = textX;\n  rstyle.labelY = textY;\n\n  this.applyLabelDimensions( node );\n};\n\nBRp.recalculateEdgeLabelProjection = function( edge ){\n  var content = edge._private.style['label'].strValue;\n  if( !content || content.match(/^\\s+$/) ){ return; }\n\n  var textX, textY;\n  var _p = edge._private;\n  var rs = _p.rscratch;\n  //var style = _p.style;\n  var rstyle = _p.rstyle;\n\n  textX = rs.midX;\n  textY = rs.midY;\n\n  // add center point to style so bounding box calculations can use it\n  rs.labelX = textX;\n  rs.labelY = textY;\n  rstyle.labelX = textX;\n  rstyle.labelY = textY;\n\n  this.applyLabelDimensions( edge );\n};\n\nBRp.applyLabelDimensions = function( ele ){\n  var rs = ele._private.rscratch;\n  var rstyle = ele._private.rstyle;\n\n  var text = this.getLabelText( ele );\n  var labelDims = this.calculateLabelDimensions( ele, text );\n\n  rstyle.labelWidth = labelDims.width;\n  rs.labelWidth = labelDims.width;\n\n  rstyle.labelHeight = labelDims.height;\n  rs.labelHeight = labelDims.height;\n};\n\nBRp.getLabelText = function( ele ){\n  var style = ele._private.style;\n  var text = ele._private.style['label'].strValue;\n  var textTransform = style['text-transform'].value;\n  var rscratch = ele._private.rscratch;\n\n  if (textTransform == 'none') {\n  } else if (textTransform == 'uppercase') {\n    text = text.toUpperCase();\n  } else if (textTransform == 'lowercase') {\n    text = text.toLowerCase();\n  }\n\n  if( style['text-wrap'].value === 'wrap' ){\n    //console.log('wrap');\n\n    // save recalc if the label is the same as before\n    if( rscratch.labelWrapKey === rscratch.labelKey ){\n      // console.log('wrap cache hit');\n      return rscratch.labelWrapCachedText;\n    }\n    // console.log('wrap cache miss');\n\n    var lines = text.split('\\n');\n    var maxW = style['text-max-width'].pfValue;\n    var wrappedLines = [];\n\n    for( var l = 0; l < lines.length; l++ ){\n      var line = lines[l];\n      var lineDims = this.calculateLabelDimensions( ele, line, 'line=' + line );\n      var lineW = lineDims.width;\n\n      if( lineW > maxW ){ // line is too long\n        var words = line.split(/\\s+/); // NB: assume collapsed whitespace into single space\n        var subline = '';\n\n        for( var w = 0; w < words.length; w++ ){\n          var word = words[w];\n          var testLine = subline.length === 0 ? word : subline + ' ' + word;\n          var testDims = this.calculateLabelDimensions( ele, testLine, 'testLine=' + testLine );\n          var testW = testDims.width;\n\n          if( testW <= maxW ){ // word fits on current line\n            subline += word + ' ';\n          } else { // word starts new line\n            wrappedLines.push( subline );\n            subline = word + ' ';\n          }\n        }\n\n        // if there's remaining text, put it in a wrapped line\n        if( !subline.match(/^\\s+$/) ){\n          wrappedLines.push( subline );\n        }\n      } else { // line is already short enough\n        wrappedLines.push( line );\n      }\n    } // for\n\n    rscratch.labelWrapCachedLines = wrappedLines;\n    rscratch.labelWrapCachedText = text = wrappedLines.join('\\n');\n    rscratch.labelWrapKey = rscratch.labelKey;\n\n    // console.log(text)\n  } // if wrap\n\n  return text;\n};\n\nBRp.calculateLabelDimensions = function( ele, text, extraKey ){\n  var r = this;\n  var style = ele._private.style;\n  var fStyle = style['font-style'].strValue;\n  var size = style['font-size'].pfValue + 'px';\n  var family = style['font-family'].strValue;\n  // var variant = style['font-variant'].strValue;\n  var weight = style['font-weight'].strValue;\n\n  var cacheKey = ele._private.labelKey;\n\n  if( extraKey ){\n    cacheKey += '$@$' + extraKey;\n  }\n\n  var cache = r.labelDimCache || (r.labelDimCache = {});\n\n  if( cache[cacheKey] ){\n    return cache[cacheKey];\n  }\n\n  var div = this.labelCalcDiv;\n\n  if( !div ){\n    div = this.labelCalcDiv = document.createElement('div');\n    document.body.appendChild( div );\n  }\n\n  var ds = div.style;\n\n  // from ele style\n  ds.fontFamily = family;\n  ds.fontStyle = fStyle;\n  ds.fontSize = size;\n  // ds.fontVariant = variant;\n  ds.fontWeight = weight;\n\n  // forced style\n  ds.position = 'absolute';\n  ds.left = '-9999px';\n  ds.top = '-9999px';\n  ds.zIndex = '-1';\n  ds.visibility = 'hidden';\n  ds.pointerEvents = 'none';\n  ds.padding = '0';\n  ds.lineHeight = '1';\n\n  if( style['text-wrap'].value === 'wrap' ){\n    ds.whiteSpace = 'pre'; // so newlines are taken into account\n  } else {\n    ds.whiteSpace = 'normal';\n  }\n\n  // put label content in div\n  div.textContent = text;\n\n  cache[cacheKey] = {\n    width: div.clientWidth,\n    height: div.clientHeight\n  };\n\n  return cache[cacheKey];\n};\n\nBRp.recalculateRenderedStyle = function( eles ){\n  var edges = [];\n  var nodes = [];\n  var handledEdge = {};\n\n  for( var i = 0; i < eles.length; i++ ){\n    var ele = eles[i];\n    var _p = ele._private;\n    var style = _p.style;\n    var rs = _p.rscratch;\n    var rstyle = _p.rstyle;\n    var id = _p.data.id;\n    var bbStyleSame = rs.boundingBoxKey != null && _p.boundingBoxKey === rs.boundingBoxKey;\n    var labelStyleSame = rs.labelKey != null && _p.labelKey === rs.labelKey;\n    var styleSame = bbStyleSame && labelStyleSame;\n\n    if( _p.group === 'nodes' ){\n      var pos = _p.position;\n      var posSame = rstyle.nodeX != null && rstyle.nodeY != null && pos.x === rstyle.nodeX && pos.y === rstyle.nodeY;\n      var wSame = rstyle.nodeW != null && rstyle.nodeW === style['width'].pfValue;\n      var hSame = rstyle.nodeH != null && rstyle.nodeH === style['height'].pfValue;\n\n      if( !posSame || !styleSame || !wSame || !hSame ){\n        nodes.push( ele );\n      }\n\n      rstyle.nodeX = pos.x;\n      rstyle.nodeY = pos.y;\n      rstyle.nodeW = style['width'].pfValue;\n      rstyle.nodeH = style['height'].pfValue;\n    } else { // edges\n\n      var srcPos = _p.source._private.position;\n      var tgtPos = _p.target._private.position;\n      var srcSame = rstyle.srcX != null && rstyle.srcY != null && srcPos.x === rstyle.srcX && srcPos.y === rstyle.srcY;\n      var tgtSame = rstyle.tgtX != null && rstyle.tgtY != null && tgtPos.x === rstyle.tgtX && tgtPos.y === rstyle.tgtY;\n      var positionsSame = srcSame && tgtSame;\n\n      if( !positionsSame || !styleSame ){\n        if( rs.edgeType === 'bezier' || rs.edgeType === 'straight' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n          if( !handledEdge[ id ] ){\n            edges.push( ele );\n            handledEdge[ id ] = true;\n\n            var parallelEdges = ele.parallelEdges();\n            for( var i = 0; i < parallelEdges.length; i++ ){\n              var pEdge = parallelEdges[i];\n              var pId = pEdge._private.data.id;\n\n              if( !handledEdge[ pId ] ){\n                edges.push( pEdge );\n                handledEdge[ pId ] = true;\n              }\n\n            }\n          }\n        } else {\n          edges.push( ele );\n        }\n      } // if positions diff\n\n      // update rstyle positions\n      rstyle.srcX = srcPos.x;\n      rstyle.srcY = srcPos.y;\n      rstyle.tgtX = tgtPos.x;\n      rstyle.tgtY = tgtPos.y;\n\n    } // if edges\n\n    rs.boundingBoxKey = _p.boundingBoxKey;\n    rs.labelKey = _p.labelKey;\n  }\n\n  this.recalculateEdgeProjections( edges );\n  this.recalculateLabelProjections( nodes, edges );\n};\n\nBRp.recalculateLabelProjections = function( nodes, edges ){\n  for( var i = 0; i < nodes.length; i++ ){\n    this.recalculateNodeLabelProjection( nodes[i] );\n  }\n\n  for( var i = 0; i < edges.length; i++ ){\n    this.recalculateEdgeLabelProjection( edges[i] );\n  }\n};\n\nBRp.recalculateEdgeProjections = function( edges ){\n  this.findEdgeControlPoints( edges );\n};\n\n\n// Find edge control points\nBRp.findEdgeControlPoints = function(edges) {\n  if( !edges || edges.length === 0 ){ return; }\n\n  var r = this;\n  var cy = r.cy;\n  var hasCompounds = cy.hasCompoundNodes();\n  var hashTable = {};\n  var pairIds = [];\n  var haystackEdges = [];\n  var autorotateEdges = [];\n\n  // create a table of edge (src, tgt) => list of edges between them\n  var pairId;\n  for (var i = 0; i < edges.length; i++){\n    var edge = edges[i];\n    var _p = edge._private;\n    var data = _p.data;\n    var style = _p.style;\n    var curveStyle = style['curve-style'].value;\n    var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';\n\n    // ignore edges who are not to be displayed\n    // they shouldn't take up space\n    if( style.display.value === 'none' ){\n      continue;\n    }\n\n    if( style['edge-text-rotation'].strValue === 'autorotate' ){\n      autorotateEdges.push( edge );\n    }\n\n    if( curveStyle === 'haystack' ){\n      haystackEdges.push( edge );\n      continue;\n    }\n\n    var srcId = data.source;\n    var tgtId = data.target;\n\n    pairId = srcId > tgtId ?\n      tgtId + '$-$' + srcId :\n      srcId + '$-$' + tgtId ;\n\n    if( edgeIsUnbundled ){\n      pairId = 'unbundled' + '$-$' + data.id;\n    }\n\n    if( hashTable[pairId] == null ){\n      hashTable[pairId] = [];\n      pairIds.push( pairId );\n    }\n\n    hashTable[pairId].push( edge );\n\n    if( edgeIsUnbundled ){\n      hashTable[pairId].hasUnbundled = true;\n    }\n  }\n\n  var src, tgt, src_p, tgt_p, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape;\n  var vectorNormInverse;\n  var badBezier;\n\n  // for each pair (src, tgt), create the ctrl pts\n  // Nested for loop is OK; total number of iterations for both loops = edgeCount\n  for (var p = 0; p < pairIds.length; p++) {\n    pairId = pairIds[p];\n    var pairEdges = hashTable[pairId];\n\n    // for each pair id, the edges should be sorted by index\n    pairEdges.sort(function(edge1, edge2){\n      return edge1._private.index - edge2._private.index;\n    });\n\n    src = pairEdges[0]._private.source;\n    tgt = pairEdges[0]._private.target;\n\n    src_p = src._private;\n    tgt_p = tgt._private;\n\n    // make sure src/tgt distinction is consistent\n    // (src/tgt in this case are just for ctrlpts and don't actually have to be true src/tgt)\n    if( src_p.data.id > tgt_p.data.id ){\n      var temp = src;\n      src = tgt;\n      tgt = temp;\n    }\n\n    srcPos = src_p.position;\n    tgtPos = tgt_p.position;\n\n    srcW = src.outerWidth();\n    srcH = src.outerHeight();\n\n    tgtW = tgt.outerWidth();\n    tgtH = tgt.outerHeight();\n\n    srcShape = r.nodeShapes[ this.getNodeShape(src) ];\n    tgtShape = r.nodeShapes[ this.getNodeShape(tgt) ];\n\n    badBezier = false;\n\n\n    if( (pairEdges.length > 1 && src !== tgt) || pairEdges.hasUnbundled ){\n\n      // pt outside src shape to calc distance/displacement from src to tgt\n      var srcOutside = srcShape.intersectLine(\n        srcPos.x,\n        srcPos.y,\n        srcW,\n        srcH,\n        tgtPos.x,\n        tgtPos.y,\n        0\n      );\n\n      // pt outside tgt shape to calc distance/displacement from src to tgt\n      var tgtOutside = tgtShape.intersectLine(\n        tgtPos.x,\n        tgtPos.y,\n        tgtW,\n        tgtH,\n        srcPos.x,\n        srcPos.y,\n        0\n      );\n\n      var midptSrcPts = {\n        x1: srcOutside[0],\n        x2: tgtOutside[0],\n        y1: srcOutside[1],\n        y2: tgtOutside[1]\n      };\n\n      var dy = ( tgtOutside[1] - srcOutside[1] );\n      var dx = ( tgtOutside[0] - srcOutside[0] );\n      var l = Math.sqrt( dx*dx + dy*dy );\n\n      var vector = {\n        x: dx,\n        y: dy\n      };\n\n      var vectorNorm = {\n        x: vector.x/l,\n        y: vector.y/l\n      };\n      vectorNormInverse = {\n        x: -vectorNorm.y,\n        y: vectorNorm.x\n      };\n\n\n      // if src intersection is inside tgt or tgt intersection is inside src, then no ctrl pts to draw\n      if(\n        tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y )  ||\n        srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y )\n      ){\n        vectorNormInverse = {};\n        badBezier = true;\n      }\n\n    }\n\n    var edge;\n    var edge_p;\n    var rs;\n\n    for (var i = 0; i < pairEdges.length; i++) {\n      edge = pairEdges[i];\n      edge_p = edge._private;\n      rs = edge_p.rscratch;\n\n      var edgeIndex1 = rs.lastEdgeIndex;\n      var edgeIndex2 = i;\n\n      var numEdges1 = rs.lastNumEdges;\n      var numEdges2 = pairEdges.length;\n\n      var eStyle = edge_p.style;\n      var style = eStyle;\n      var curveStyle = eStyle['curve-style'].value;\n      var ctrlptDists = eStyle['control-point-distances'];\n      var ctrlptWs = eStyle['control-point-weights'];\n      var bezierN = ctrlptDists && ctrlptWs ? Math.min( ctrlptDists.value.length, ctrlptWs.value.length ) : 1;\n      var stepSize = eStyle['control-point-step-size'].pfValue;\n      var ctrlptDist = ctrlptDists !== undefined ? ctrlptDists.pfValue[0] : undefined;\n      var ctrlptWeight = ctrlptWs.value[0];\n      var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';\n\n      var swappedDirection = edge_p.source !== src;\n\n      if( swappedDirection && edgeIsUnbundled ){\n        ctrlptDist *= -1;\n      }\n\n      var srcX1 = rs.lastSrcCtlPtX;\n      var srcX2 = srcPos.x;\n      var srcY1 = rs.lastSrcCtlPtY;\n      var srcY2 = srcPos.y;\n      var srcW1 = rs.lastSrcCtlPtW;\n      var srcW2 = src.outerWidth();\n      var srcH1 = rs.lastSrcCtlPtH;\n      var srcH2 = src.outerHeight();\n\n      var tgtX1 = rs.lastTgtCtlPtX;\n      var tgtX2 = tgtPos.x;\n      var tgtY1 = rs.lastTgtCtlPtY;\n      var tgtY2 = tgtPos.y;\n      var tgtW1 = rs.lastTgtCtlPtW;\n      var tgtW2 = tgt.outerWidth();\n      var tgtH1 = rs.lastTgtCtlPtH;\n      var tgtH2 = tgt.outerHeight();\n\n      var width1 = rs.lastW;\n      var width2 = eStyle['control-point-step-size'].pfValue;\n\n      if( badBezier ){\n        rs.badBezier = true;\n      } else {\n        rs.badBezier = false;\n      }\n\n      if( srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2\n      &&  tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2\n      &&  width1 === width2\n      &&  ((edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2) || edgeIsUnbundled) ){\n        // console.log('edge ctrl pt cache HIT')\n        continue; // then the control points haven't changed and we can skip calculating them\n      } else {\n        rs.lastSrcCtlPtX = srcX2;\n        rs.lastSrcCtlPtY = srcY2;\n        rs.lastSrcCtlPtW = srcW2;\n        rs.lastSrcCtlPtH = srcH2;\n        rs.lastTgtCtlPtX = tgtX2;\n        rs.lastTgtCtlPtY = tgtY2;\n        rs.lastTgtCtlPtW = tgtW2;\n        rs.lastTgtCtlPtH = tgtH2;\n        rs.lastEdgeIndex = edgeIndex2;\n        rs.lastNumEdges = numEdges2;\n        rs.lastWidth = width2;\n        // console.log('edge ctrl pt cache MISS')\n      }\n\n      if( src === tgt ){\n        // Self-edge\n\n        rs.edgeType = 'self';\n\n        var j = i;\n        var loopDist = stepSize;\n\n        if( edgeIsUnbundled ){\n          j = 0;\n          loopDist = ctrlptDist;\n        }\n\n        rs.ctrlpts = [\n          srcPos.x,\n          srcPos.y - (1 + Math.pow(srcH, 1.12) / 100) * loopDist * (j / 3 + 1),\n\n          srcPos.x - (1 + Math.pow(srcW, 1.12) / 100) * loopDist * (j / 3 + 1),\n          srcPos.y\n        ];\n\n      } else if(\n        hasCompounds &&\n        ( src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild() ) &&\n        ( src.parents().anySame(tgt) || tgt.parents().anySame(src) )\n      ){\n        // Compound edge\n\n        rs.edgeType = 'compound';\n\n        // because the line approximation doesn't apply for compound beziers\n        // (loop/self edges are already elided b/c of cheap src==tgt check)\n        rs.badBezier = false;\n\n        var j = i;\n        var loopDist = stepSize;\n\n        if( edgeIsUnbundled ){\n          j = 0;\n          loopDist = ctrlptDist;\n        }\n\n        var loopW = 50;\n\n        var loopaPos = {\n          x: srcPos.x - srcW/2,\n          y: srcPos.y - srcH/2\n        };\n\n        var loopbPos = {\n          x: tgtPos.x - tgtW/2,\n          y: tgtPos.y - tgtH/2\n        };\n\n        var loopPos = {\n          x: Math.min( loopaPos.x, loopbPos.x ),\n          y: Math.min( loopaPos.y, loopbPos.y )\n        };\n\n        // avoids cases with impossible beziers\n        var minCompoundStretch = 0.5;\n        var compoundStretchA = Math.max( minCompoundStretch, Math.log(srcW * 0.01) );\n        var compoundStretchB = Math.max( minCompoundStretch, Math.log(tgtW * 0.01) );\n\n        rs.ctrlpts = [\n          loopPos.x,\n          loopPos.y - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchA,\n\n          loopPos.x - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchB,\n          loopPos.y\n        ];\n\n      } else if( curveStyle === 'segments' ){\n        // Segments (multiple straight lines)\n\n        rs.edgeType = 'segments';\n        rs.segpts = [];\n\n        var segmentWs = eStyle['segment-weights'].pfValue;\n        var segmentDs = eStyle['segment-distances'].pfValue;\n        var segmentsN = Math.min( segmentWs.length, segmentDs.length );\n\n        for( var s = 0; s < segmentsN; s++ ){\n          var w = segmentWs[s];\n          var d = segmentDs[s];\n\n          // d = swappedDirection ? -d : d;\n          //\n          // d = Math.abs(d);\n\n          // var w1 = !swappedDirection ? (1 - w) : w;\n          // var w2 = !swappedDirection ? w : (1 - w);\n\n          var w1 = (1 - w);\n          var w2 = w;\n\n          var adjustedMidpt = {\n            x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,\n            y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2\n          };\n\n          rs.segpts.push(\n            adjustedMidpt.x + vectorNormInverse.x * d,\n            adjustedMidpt.y + vectorNormInverse.y * d\n          );\n        }\n\n      // Straight edge\n      } else if (\n        pairEdges.length % 2 === 1\n        && i === Math.floor(pairEdges.length / 2)\n        && !edgeIsUnbundled\n      ){\n\n        rs.edgeType = 'straight';\n\n      } else {\n        // (Multi)bezier\n\n        var multi = edgeIsUnbundled;\n\n        rs.edgeType = multi ? 'multibezier' : 'bezier';\n        rs.ctrlpts = [];\n\n        for( var b = 0; b < bezierN; b++ ){\n          var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize;\n          var manctrlptDist;\n          var sign = math.signum( normctrlptDist );\n\n          if( multi ){\n            ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[b] : stepSize; // fall back on step size\n            ctrlptWeight = ctrlptWs.value[b];\n          }\n\n          if( edgeIsUnbundled ){ // multi or single unbundled\n            manctrlptDist = ctrlptDist;\n          } else {\n            manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined;\n          }\n\n          var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist;\n\n          var w1 = !swappedDirection || edgeIsUnbundled ? (1 - ctrlptWeight) : ctrlptWeight;\n          var w2 = !swappedDirection || edgeIsUnbundled ? ctrlptWeight : (1 - ctrlptWeight);\n\n          var adjustedMidpt = {\n            x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,\n            y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2\n          };\n\n          rs.ctrlpts.push(\n            adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint,\n            adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint\n          );\n        }\n\n      }\n\n      // find endpts for edge\n      this.findEndpoints( edge );\n\n      var badStart = !is.number( rs.startX ) || !is.number( rs.startY );\n      var badAStart = !is.number( rs.arrowStartX ) || !is.number( rs.arrowStartY );\n      var badEnd = !is.number( rs.endX ) || !is.number( rs.endY );\n      var badAEnd = !is.number( rs.arrowEndX ) || !is.number( rs.arrowEndY );\n\n      var minCpADistFactor = 3;\n      var arrowW = this.getArrowWidth( eStyle['width'].pfValue ) * this.arrowShapeHeight;\n      var minCpADist = minCpADistFactor * arrowW;\n\n      if( rs.edgeType === 'bezier' ){\n        var startACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY } );\n        var closeStartACp = startACpDist < minCpADist;\n        var endACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY } );\n        var closeEndACp = endACpDist < minCpADist;\n\n        var overlapping = false;\n\n        if( badStart || badAStart || closeStartACp ){\n          overlapping = true;\n\n          // project control point along line from src centre to outside the src shape\n          // (otherwise intersection will yield nothing)\n          var cpD = { // delta\n            x: rs.ctrlpts[0] - srcPos.x,\n            y: rs.ctrlpts[1] - srcPos.y\n          };\n          var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line\n          var cpM = { // normalised delta\n            x: cpD.x / cpL,\n            y: cpD.y / cpL\n          };\n          var radius = Math.max(srcW, srcH);\n          var cpProj = { // *2 radius guarantees outside shape\n            x: rs.ctrlpts[0] + cpM.x * 2 * radius,\n            y: rs.ctrlpts[1] + cpM.y * 2 * radius\n          };\n\n          var srcCtrlPtIntn = srcShape.intersectLine(\n            srcPos.x,\n            srcPos.y,\n            srcW,\n            srcH,\n            cpProj.x,\n            cpProj.y,\n            0\n          );\n\n          if( closeStartACp ){\n            rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist);\n            rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist);\n          } else {\n            rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist;\n            rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist;\n          }\n        }\n\n        if( badEnd || badAEnd || closeEndACp ){\n          overlapping = true;\n\n          // project control point along line from tgt centre to outside the tgt shape\n          // (otherwise intersection will yield nothing)\n          var cpD = { // delta\n            x: rs.ctrlpts[0] - tgtPos.x,\n            y: rs.ctrlpts[1] - tgtPos.y\n          };\n          var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line\n          var cpM = { // normalised delta\n            x: cpD.x / cpL,\n            y: cpD.y / cpL\n          };\n          var radius = Math.max(srcW, srcH);\n          var cpProj = { // *2 radius guarantees outside shape\n            x: rs.ctrlpts[0] + cpM.x * 2 * radius,\n            y: rs.ctrlpts[1] + cpM.y * 2 * radius\n          };\n\n          var tgtCtrlPtIntn = tgtShape.intersectLine(\n            tgtPos.x,\n            tgtPos.y,\n            tgtW,\n            tgtH,\n            cpProj.x,\n            cpProj.y,\n            0\n          );\n\n          if( closeEndACp ){\n            rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist);\n            rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist);\n          } else {\n            rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist;\n            rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist;\n          }\n\n        }\n\n        if( overlapping ){\n          // recalc endpts\n          this.findEndpoints( edge );\n        }\n\n      }\n\n      if( rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n        rs.allpts = [];\n\n        rs.allpts.push( rs.startX, rs.startY );\n\n        for( var b = 0; b+1 < rs.ctrlpts.length; b += 2 ){\n          // ctrl pt itself\n          rs.allpts.push( rs.ctrlpts[b], rs.ctrlpts[b+1] );\n\n          // the midpt between ctrlpts as intermediate destination pts\n          if( b + 3 < rs.ctrlpts.length ){\n            rs.allpts.push( (rs.ctrlpts[b] + rs.ctrlpts[b+2])/2, (rs.ctrlpts[b+1] + rs.ctrlpts[b+3])/2 );\n          }\n        }\n\n        rs.allpts.push( rs.endX, rs.endY );\n\n        var m, mt;\n        if( rs.edgeType === 'bezier' ){\n          rs.midX = math.qbezierAt( rs.arrowStartX, rs.ctrlpts[0], rs.arrowEndX, 0.5 );\n          rs.midY = math.qbezierAt( rs.arrowStartY, rs.ctrlpts[1], rs.arrowEndY, 0.5 );\n        } else if( rs.ctrlpts.length/2 % 2 === 0 ){\n          m = rs.allpts.length/2 - 1;\n\n          rs.midX = rs.allpts[m];\n          rs.midY = rs.allpts[m+1];\n        } else {\n          m = rs.allpts.length/2 - 3;\n          mt = 0.5;\n\n          rs.midX = math.qbezierAt( rs.allpts[m], rs.allpts[m+2], rs.allpts[m+4], mt );\n          rs.midY = math.qbezierAt( rs.allpts[m+1], rs.allpts[m+3], rs.allpts[m+5], mt );\n        }\n\n      } else if( rs.edgeType === 'straight' ){\n        // need to calc these after endpts\n        rs.allpts = [ rs.startX, rs.startY, rs.endX, rs.endY ];\n\n        // default midpt for labels etc\n        rs.midX = ( rs.arrowStartX + rs.arrowEndX )/2;\n        rs.midY = ( rs.arrowStartY + rs.arrowEndY )/2;\n\n      } else if( rs.edgeType === 'segments' ){\n        rs.allpts = [];\n        rs.allpts.push( rs.startX, rs.startY );\n        rs.allpts.push.apply( rs.allpts, rs.segpts );\n        rs.allpts.push( rs.endX, rs.endY );\n\n        if( rs.segpts.length % 4 === 0 ){\n          var i2 = rs.segpts.length / 2;\n          var i1 = i2 - 2;\n\n          rs.midX = ( rs.segpts[i1] + rs.segpts[i2] ) / 2;\n          rs.midY = ( rs.segpts[i1+1] + rs.segpts[i2+1] ) / 2;\n        } else {\n          var i1 = rs.segpts.length / 2 - 1;\n\n          rs.midX = rs.segpts[i1];\n          rs.midY = rs.segpts[i1+1];\n        }\n\n\n      }\n\n      this.projectLines( edge );\n      this.calculateArrowAngles( edge );\n      this.recalculateEdgeLabelProjection( edge );\n\n    }\n  }\n\n  for( var i = 0; i < haystackEdges.length; i++ ){\n    var edge = haystackEdges[i];\n    var _p = edge._private;\n    var style = _p.style;\n    var rscratch = _p.rscratch;\n    var rs = rscratch;\n\n    if( !rscratch.haystack ){\n      var angle = Math.random() * 2 * Math.PI;\n\n      rscratch.source = {\n        x: Math.cos(angle),\n        y: Math.sin(angle)\n      };\n\n      var angle = Math.random() * 2 * Math.PI;\n\n      rscratch.target = {\n        x: Math.cos(angle),\n        y: Math.sin(angle)\n      };\n\n    }\n\n    var src = _p.source;\n    var tgt = _p.target;\n    var srcPos = src._private.position;\n    var tgtPos = tgt._private.position;\n    var srcW = src.width();\n    var tgtW = tgt.width();\n    var srcH = src.height();\n    var tgtH = tgt.height();\n    var radius = style['haystack-radius'].value;\n    var halfRadius = radius/2; // b/c have to half width/height\n\n    rs.haystackPts = rs.allpts = [\n      rs.source.x * srcW * halfRadius + srcPos.x,\n      rs.source.y * srcH * halfRadius + srcPos.y,\n      rs.target.x * tgtW * halfRadius + tgtPos.x,\n      rs.target.y * tgtH * halfRadius + tgtPos.y\n    ];\n\n    rs.midX = (rs.allpts[0] + rs.allpts[2])/2;\n    rs.midY = (rs.allpts[1] + rs.allpts[3])/2;\n\n    // always override as haystack in case set to different type previously\n    rscratch.edgeType = 'haystack';\n    rscratch.haystack = true;\n\n    this.projectLines( edge );\n    this.calculateArrowAngles( edge );\n    this.recalculateEdgeLabelProjection( edge );\n  }\n\n  for( var i = 0 ; i < autorotateEdges.length; i++ ){\n    var edge = autorotateEdges[i];\n    var rs = edge._private.rscratch;\n\n    rs.labelAngle = Math.atan( rs.midDispY / rs.midDispX );\n  }\n\n  return hashTable;\n};\n\nvar getAngleFromDisp = function( dispX, dispY ){\n  return Math.atan2( dispY, dispX ) - Math.PI/2;\n};\n\nBRp.calculateArrowAngles = function( edge ){\n  var rs = edge._private.rscratch;\n  var isHaystack = rs.edgeType === 'haystack';\n  var isMultibezier = rs.edgeType === 'multibezier';\n  var isSegments = rs.edgeType === 'segments';\n  var isCompound = rs.edgeType === 'compound';\n  var isSelf = rs.edgeType === 'self';\n\n  // Displacement gives direction for arrowhead orientation\n  var dispX, dispY;\n  var startX, startY, endX, endY;\n\n  var srcPos = edge.source().position();\n  var tgtPos = edge.target().position();\n\n  if( isHaystack ){\n    startX = rs.haystackPts[0];\n    startY = rs.haystackPts[1];\n    endX = rs.haystackPts[2];\n    endY = rs.haystackPts[3];\n  } else {\n    startX = rs.arrowStartX;\n    startY = rs.arrowStartY;\n    endX = rs.arrowEndX;\n    endY = rs.arrowEndY;\n  }\n\n  // source\n  //\n\n  dispX = srcPos.x - startX;\n  dispY = srcPos.y - startY;\n\n  rs.srcArrowAngle = getAngleFromDisp( dispX, dispY );\n\n  // mid target\n  //\n\n  var midX = rs.midX;\n  var midY = rs.midY;\n\n  if( isHaystack ){\n    midX = ( startX + endX )/2;\n    midY = ( startY + endY )/2;\n  }\n\n  dispX = endX - startX;\n  dispY = endY - startY;\n\n  if( isSelf ){\n    dispX = -1;\n    dispY = 1;\n  } else if( isSegments ){\n    var pts = rs.allpts;\n\n    if( pts.length / 2 % 2 === 0 ){\n      var i2 = pts.length / 2;\n      var i1 = i2 - 2;\n\n      dispX = ( pts[i2] - pts[i1] );\n      dispY = ( pts[i2+1] - pts[i1+1] );\n    } else {\n      var i2 = pts.length / 2 - 1;\n      var i1 = i2 - 2;\n      var i3 = i2 + 2;\n\n      dispX = ( pts[i2] - pts[i1] );\n      dispY = ( pts[i2+1] - pts[i1+1] );\n    }\n  } else if( isMultibezier || isCompound ){\n    var pts = rs.allpts;\n    var cpts = rs.ctrlpts;\n    var bp0x, bp0y;\n    var bp1x, bp1y;\n\n    if( cpts.length / 2 % 2 === 0 ){\n      var p0 = pts.length / 2 - 1; // startpt\n      var ic = p0 + 2;\n      var p1 = ic + 2;\n\n      bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0 );\n      bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0 );\n\n      bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0001 );\n      bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0001 );\n    } else {\n      var ic = pts.length / 2 - 1; // ctrpt\n      var p0 = ic - 2; // startpt\n      var p1 = ic + 2; // endpt\n\n      bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.4999 );\n      bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.4999 );\n\n      bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.5 );\n      bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.5 );\n    }\n\n    dispX = ( bp1x - bp0x );\n    dispY = ( bp1y - bp0y );\n  }\n\n  rs.midtgtArrowAngle = getAngleFromDisp( dispX, dispY );\n\n  rs.midDispX = dispX;\n  rs.midDispY = dispY;\n\n  // mid source\n  //\n\n  dispX *= -1;\n  dispY *= -1;\n\n  if( isSegments ){\n    var pts = rs.allpts;\n\n    if( pts.length / 2 % 2 === 0 ){\n      // already ok\n    } else {\n      var i2 = pts.length / 2 - 1;\n      var i3 = i2 + 2;\n\n      dispX = -( pts[i3] - pts[i2] );\n      dispY = -( pts[i3+1] - pts[i2+1] );\n    }\n  }\n\n  rs.midsrcArrowAngle = getAngleFromDisp( dispX, dispY );\n\n  // target\n  //\n\n  dispX = tgtPos.x - endX;\n  dispY = tgtPos.y - endY;\n\n  rs.tgtArrowAngle = getAngleFromDisp( dispX, dispY );\n};\n\n\nBRp.findEndpoints = function( edge ){\n  var r = this;\n  var intersect;\n\n  var source = edge.source()[0];\n  var target = edge.target()[0];\n\n  var src_p = source._private;\n  var tgt_p = target._private;\n\n  var srcPos = src_p.position;\n  var tgtPos = tgt_p.position;\n\n  var tgtArShape = edge._private.style['target-arrow-shape'].value;\n  var srcArShape = edge._private.style['source-arrow-shape'].value;\n\n  var rs = edge._private.rscratch;\n\n  var et = rs.edgeType;\n  var bezier = et === 'bezier' || et === 'multibezier' || et === 'self' || et === 'compound';\n  var multi = et !== 'bezier';\n  var lines = et === 'straight' || et === 'segments';\n  var segments = et === 'segments';\n\n  var p1, p2;\n\n  if( bezier ){\n    var cpStart = [ rs.ctrlpts[0], rs.ctrlpts[1] ];\n    var cpEnd = multi ? [ rs.ctrlpts[rs.ctrlpts.length - 2], rs.ctrlpts[rs.ctrlpts.length - 1] ] : cpStart;\n\n    p1 = cpEnd;\n    p2 = cpStart;\n  } else if( lines ){\n    var srcArrowFromPt = !segments ? [ tgtPos.x, tgtPos.y ] : rs.segpts.slice( 0, 2 );\n    var tgtArrowFromPt = !segments ? [ srcPos.x, srcPos.y ] : rs.segpts.slice( rs.segpts.length - 2 );\n\n    p1 = tgtArrowFromPt;\n    p2 = srcArrowFromPt;\n  }\n\n  intersect = r.nodeShapes[this.getNodeShape(target)].intersectLine(\n    tgtPos.x,\n    tgtPos.y,\n    target.outerWidth(),\n    target.outerHeight(),\n    p1[0],\n    p1[1],\n    0\n  );\n\n  var arrowEnd = math.shortenIntersection(intersect, p1,\n    r.arrowShapes[tgtArShape].spacing(edge));\n  var edgeEnd = math.shortenIntersection(intersect, p1,\n    r.arrowShapes[tgtArShape].gap(edge));\n\n  rs.endX = edgeEnd[0];\n  rs.endY = edgeEnd[1];\n\n  rs.arrowEndX = arrowEnd[0];\n  rs.arrowEndY = arrowEnd[1];\n\n  intersect = r.nodeShapes[this.getNodeShape(source)].intersectLine(\n    srcPos.x,\n    srcPos.y,\n    source.outerWidth(),\n    source.outerHeight(),\n    p2[0],\n    p2[1],\n    0\n  );\n\n  var arrowStart = math.shortenIntersection(\n    intersect, p2,\n    r.arrowShapes[srcArShape].spacing(edge)\n  );\n  var edgeStart = math.shortenIntersection(\n    intersect, p2,\n    r.arrowShapes[srcArShape].gap(edge)\n  );\n\n  rs.startX = edgeStart[0];\n  rs.startY = edgeStart[1];\n\n  rs.arrowStartX = arrowStart[0];\n  rs.arrowStartY = arrowStart[1];\n\n  if( lines ){\n    if( !is.number(rs.startX) || !is.number(rs.startY) || !is.number(rs.endX) || !is.number(rs.endY) ){\n      rs.badLine = true;\n    } else {\n      rs.badLine = false;\n    }\n  }\n};\n\nBRp.getArrowWidth = BRp.getArrowHeight = function(edgeWidth) {\n  var cache = this.arrowWidthCache = this.arrowWidthCache || {};\n\n  var cachedVal = cache[edgeWidth];\n  if( cachedVal ){\n    return cachedVal;\n  }\n\n  cachedVal =  Math.max(Math.pow(edgeWidth * 13.37, 0.9), 29);\n  cache[edgeWidth] = cachedVal;\n\n  return cachedVal;\n};\n\nmodule.exports = BRp;\n\n},{\"../../../collection/zsort\":29,\"../../../is\":77,\"../../../math\":79}],57:[function(_dereq_,module,exports){\n'use strict';\n\nvar BRp = {};\n\nBRp.getCachedImage = function(url, onLoad) {\n  var r = this;\n  var imageCache = r.imageCache = r.imageCache || {};\n\n  if( imageCache[url] && imageCache[url].image ){\n    return imageCache[url].image;\n  }\n\n  var cache = imageCache[url] = imageCache[url] || {};\n\n  var image = cache.image = new Image();\n  image.addEventListener('load', onLoad);\n  image.src = url;\n\n  return image;\n};\n\nmodule.exports = BRp;\n\n},{}],58:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../../is');\nvar util = _dereq_('../../../util');\n\nvar BaseRenderer = function(){};\nvar BR = BaseRenderer;\nvar BRp = BR.prototype;\n\nBRp.clientFunctions = [ 'redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl' ];\n\nBRp.init = function( options ){\n  var r = this;\n\n  r.options = options;\n\n  r.cy = options.cy;\n\n  r.container = options.cy.container();\n\n  r.selection = [undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag\n\n  //--Pointer-related data\n  r.hoverData = {down: null, last: null,\n      downTime: null, triggerMode: null,\n      dragging: false,\n      initialPan: [null, null], capture: false};\n\n  r.dragData = {possibleDragElements: []};\n\n  r.touchData = {\n      start: null, capture: false,\n\n      // These 3 fields related to tap, taphold events\n      startPosition: [null, null, null, null, null, null],\n      singleTouchStartTime: null,\n      singleTouchMoved: true,\n\n      now: [null, null, null, null, null, null],\n      earlier: [null, null, null, null, null, null]\n  };\n\n  r.redraws = 0;\n  r.showFps = options.showFps;\n\n  r.hideEdgesOnViewport = options.hideEdgesOnViewport;\n  r.hideLabelsOnViewport = options.hideLabelsOnViewport;\n  r.textureOnViewport = options.textureOnViewport;\n  r.wheelSensitivity = options.wheelSensitivity;\n  r.motionBlurEnabled = options.motionBlur; // on by default\n  r.forcedPixelRatio = options.pixelRatio;\n  r.motionBlur = true; // for initial kick off\n  r.motionBlurOpacity = options.motionBlurOpacity;\n  r.motionBlurTransparency = 1 - r.motionBlurOpacity;\n  r.motionBlurPxRatio = 1;\n  r.mbPxRBlurry = 1; //0.8;\n  r.minMbLowQualFrames = 4;\n  r.fullQualityMb = false;\n  r.clearedForMotionBlur = [];\n  r.desktopTapThreshold = options.desktopTapThreshold;\n  r.desktopTapThreshold2 = options.desktopTapThreshold * options.desktopTapThreshold;\n  r.touchTapThreshold = options.touchTapThreshold;\n  r.touchTapThreshold2 = options.touchTapThreshold * options.touchTapThreshold;\n  r.tapholdDuration = 500;\n\n  r.bindings = [];\n\n  r.registerNodeShapes();\n  r.registerArrowShapes();\n  r.load();\n};\n\nBRp.notify = function(params) {\n  var types;\n  var r = this;\n\n  if( is.array( params.type ) ){\n    types = params.type;\n\n  } else {\n    types = [ params.type ];\n  }\n\n  for( var i = 0; i < types.length; i++ ){\n    var type = types[i];\n\n    switch( type ){\n      case 'destroy':\n        r.destroy();\n        return;\n\n      case 'add':\n      case 'remove':\n      case 'load':\n        r.updateElementsCache();\n        break;\n\n      case 'viewport':\n        r.redrawHint('select', true);\n        break;\n\n      case 'style':\n        r.updateCachedZSortedEles();\n        break;\n    }\n\n    if( type === 'load' || type === 'resize' ){\n      r.invalidateContainerClientCoordsCache();\n      r.matchCanvasSize(r.container);\n    }\n  } // for\n\n  r.redrawHint('eles', true);\n  r.redrawHint('drag', true);\n\n  this.startRenderLoop();\n\n  this.redraw();\n};\n\nBRp.destroy = function(){\n  this.destroyed = true;\n\n  this.cy.stopAnimationLoop();\n\n  for( var i = 0; i < this.bindings.length; i++ ){\n    var binding = this.bindings[i];\n    var b = binding;\n\n    b.target.removeEventListener(b.event, b.handler, b.useCapture);\n  }\n\n  if( this.removeObserver ){\n    this.removeObserver.disconnect();\n  }\n\n  if( this.labelCalcDiv ){\n    try{\n      document.body.removeChild(this.labelCalcDiv);\n    } catch(e){\n      // ie10 issue #1014\n    }\n  }\n};\n\n[\n  _dereq_('./arrow-shapes'),\n  _dereq_('./cached-eles'),\n  _dereq_('./coord-ele-math'),\n  _dereq_('./images'),\n  _dereq_('./load-listeners'),\n  _dereq_('./node-shapes'),\n  _dereq_('./redraw')\n].forEach(function( props ){\n  util.extend( BRp, props );\n});\n\nmodule.exports = BR;\n\n},{\"../../../is\":77,\"../../../util\":94,\"./arrow-shapes\":54,\"./cached-eles\":55,\"./coord-ele-math\":56,\"./images\":57,\"./load-listeners\":59,\"./node-shapes\":60,\"./redraw\":61}],59:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../../is');\nvar util = _dereq_('../../../util');\nvar Event = _dereq_('../../../event');\nvar Collection = _dereq_('../../../collection');\n\nvar BRp = {};\n\nBRp.registerBinding = function(target, event, handler, useCapture){\n  this.bindings.push({\n    target: target,\n    event: event,\n    handler: handler,\n    useCapture: useCapture\n  });\n\n  target.addEventListener(event, handler, useCapture);\n};\n\nBRp.nodeIsDraggable = function(node) {\n  if (node._private.style['opacity'].value !== 0\n    && node._private.style['visibility'].value == 'visible'\n    && node._private.style['display'].value == 'element'\n    && !node.locked()\n    && node.grabbable() ) {\n\n    return true;\n  }\n\n  return false;\n};\n\nBRp.load = function() {\n  var r = this;\n\n  var triggerEvents = function( target, names, e, props ){\n    if( target == null ){\n      target = r.cy;\n    }\n\n    for( var i = 0; i < names.length; i++ ){\n      var name = names[i];\n\n      var event = Event( e, util.extend({ type: name }, props) );\n      target.trigger( event );\n    }\n  };\n\n  var isMultSelKeyDown = function( e ){\n    return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey\n  };\n\n  var getDragListIds = function(opts){\n    var listHasId;\n\n    if( opts.addToList && r.cy.hasCompoundNodes() ){ // only needed for compound graphs\n      if( !opts.addToList.hasId ){ // build ids lookup if doesn't already exist\n        opts.addToList.hasId = {};\n\n        for( var i = 0; i < opts.addToList.length; i++ ){\n          var ele = opts.addToList[i];\n\n          opts.addToList.hasId[ ele.id() ] = true;\n        }\n      }\n\n      listHasId = opts.addToList.hasId;\n    }\n\n    return listHasId || {};\n  };\n\n  // helper function to determine which child nodes and inner edges\n  // of a compound node to be dragged as well as the grabbed and selected nodes\n  var addDescendantsToDrag = function(node, opts){\n    if( !node._private.cy.hasCompoundNodes() ){\n      return;\n    }\n\n    if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do\n\n    var listHasId = getDragListIds( opts );\n\n    var innerNodes = node.descendants();\n\n    for( var i = 0; i < innerNodes.size(); i++ ){\n      var iNode = innerNodes[i];\n      var _p = iNode._private;\n\n      if( opts.inDragLayer ){\n        _p.rscratch.inDragLayer = true;\n      }\n\n      if( opts.addToList && !listHasId[ iNode.id() ] ){\n        opts.addToList.push( iNode );\n        listHasId[ iNode.id() ] = true;\n\n        _p.grabbed = true;\n      }\n\n      var edges = _p.edges;\n      for( var j = 0; opts.inDragLayer && j < edges.length; j++ ){\n        edges[j]._private.rscratch.inDragLayer = true;\n      }\n    }\n  };\n\n  // adds the given nodes, and its edges to the drag layer\n  var addNodeToDrag = function(node, opts){\n\n    var _p = node._private;\n    var listHasId = getDragListIds( opts );\n\n    if( opts.inDragLayer ){\n      _p.rscratch.inDragLayer = true;\n    }\n\n    if( opts.addToList && !listHasId[ node.id() ] ){\n      opts.addToList.push( node );\n      listHasId[ node.id() ] = true;\n\n      _p.grabbed = true;\n    }\n\n    var edges = _p.edges;\n    for( var i = 0; opts.inDragLayer && i < edges.length; i++ ){\n      edges[i]._private.rscratch.inDragLayer = true;\n    }\n\n    addDescendantsToDrag( node, opts ); // always add to drag\n\n    // also add nodes and edges related to the topmost ancestor\n    updateAncestorsInDragLayer( node, {\n      inDragLayer: opts.inDragLayer\n    } );\n  };\n\n  var freeDraggedElements = function( draggedElements ){\n    if( !draggedElements ){ return; }\n\n    for (var i=0; i < draggedElements.length; i++) {\n\n      var dEi_p = draggedElements[i]._private;\n\n      if(dEi_p.group === 'nodes') {\n        dEi_p.rscratch.inDragLayer = false;\n        dEi_p.grabbed = false;\n\n        var sEdges = dEi_p.edges;\n        for( var j = 0; j < sEdges.length; j++ ){ sEdges[j]._private.rscratch.inDragLayer = false; }\n\n        // for compound nodes, also remove related nodes and edges from the drag layer\n        updateAncestorsInDragLayer(draggedElements[i], { inDragLayer: false });\n\n      } else if( dEi_p.group === 'edges' ){\n        dEi_p.rscratch.inDragLayer = false;\n      }\n\n    }\n  };\n\n  // helper function to determine which ancestor nodes and edges should go\n  // to the drag layer (or should be removed from drag layer).\n  var updateAncestorsInDragLayer = function(node, opts) {\n\n    if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do\n\n    // find top-level parent\n    var parent = node;\n\n    if( !node._private.cy.hasCompoundNodes() ){\n      return;\n    }\n\n    while( parent.parent().nonempty() ){\n      parent = parent.parent()[0];\n    }\n\n    // no parent node: no nodes to add to the drag layer\n    if( parent == node ){\n      return;\n    }\n\n    var nodes = parent.descendants()\n      .merge( parent )\n      .unmerge( node )\n      .unmerge( node.descendants() )\n    ;\n\n    var edges = nodes.connectedEdges();\n\n    var listHasId = getDragListIds( opts );\n\n    for( var i = 0; i < nodes.size(); i++ ){\n      if( opts.inDragLayer !== undefined ){\n        nodes[i]._private.rscratch.inDragLayer = opts.inDragLayer;\n      }\n\n      if( opts.addToList && !listHasId[ nodes[i].id() ] ){\n        opts.addToList.push( nodes[i] );\n        listHasId[ nodes[i].id() ] = true;\n\n        nodes[i]._private.grabbed = true;\n      }\n    }\n\n    for( var j = 0; opts.inDragLayer !== undefined && j < edges.length; j++ ) {\n      edges[j]._private.rscratch.inDragLayer = opts.inDragLayer;\n    }\n  };\n\n  if( typeof MutationObserver !== 'undefined' ){\n    r.removeObserver = new MutationObserver(function( mutns ){\n      for( var i = 0; i < mutns.length; i++ ){\n        var mutn = mutns[i];\n        var rNodes = mutn.removedNodes;\n\n        if( rNodes ){ for( var j = 0; j < rNodes.length; j++ ){\n          var rNode = rNodes[j];\n\n          if( rNode === r.container ){\n            r.destroy();\n            break;\n          }\n        } }\n      }\n    });\n\n    if( r.container.parentNode ){\n      r.removeObserver.observe( r.container.parentNode, { childList: true } );\n    }\n  } else {\n    r.registerBinding(r.container, 'DOMNodeRemoved', function(e){\n      r.destroy();\n    });\n  }\n\n\n\n  // auto resize\n  r.registerBinding(window, 'resize', util.debounce( function(e) {\n    r.invalidateContainerClientCoordsCache();\n\n    r.matchCanvasSize(r.container);\n    r.redrawHint('eles', true);\n    r.redraw();\n  }, 100 ) );\n\n  var invalCtnrBBOnScroll = function(domEle){\n    r.registerBinding(domEle, 'scroll', function(e){\n      r.invalidateContainerClientCoordsCache();\n    } );\n  };\n\n  var bbCtnr = r.cy.container();\n\n  for( ;; ){\n\n    invalCtnrBBOnScroll( bbCtnr );\n\n    if( bbCtnr.parentNode ){\n      bbCtnr = bbCtnr.parentNode;\n    } else {\n      break;\n    }\n\n  }\n\n  // stop right click menu from appearing on cy\n  r.registerBinding(r.container, 'contextmenu', function(e){\n    e.preventDefault();\n  });\n\n  var inBoxSelection = function(){\n    return r.selection[4] !== 0;\n  };\n\n  // Primary key\n  r.registerBinding(r.container, 'mousedown', function(e) {\n    e.preventDefault();\n    r.hoverData.capture = true;\n    r.hoverData.which = e.which;\n\n    var cy = r.cy;\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n    var select = r.selection;\n    var near = r.findNearestElement(pos[0], pos[1], true, false);\n    var draggedElements = r.dragData.possibleDragElements;\n\n    r.hoverData.mdownPos = pos;\n\n    var checkForTaphold = function(){\n      r.hoverData.tapholdCancelled = false;\n\n      clearTimeout( r.hoverData.tapholdTimeout );\n\n      r.hoverData.tapholdTimeout = setTimeout(function(){\n\n        if( r.hoverData.tapholdCancelled ){\n          return;\n        } else {\n          var ele = r.hoverData.down;\n\n          if( ele ){\n            ele.trigger( Event(e, {\n              type: 'taphold',\n              cyPosition: { x: pos[0], y: pos[1] }\n            }) );\n          } else {\n            cy.trigger( Event(e, {\n              type: 'taphold',\n              cyPosition: { x: pos[0], y: pos[1] }\n            }) );\n          }\n        }\n\n      }, r.tapholdDuration);\n    };\n\n    // Right click button\n    if( e.which == 3 ){\n\n      r.hoverData.cxtStarted = true;\n\n      var cxtEvt = Event(e, {\n        type: 'cxttapstart',\n        cyPosition: { x: pos[0], y: pos[1] }\n      });\n\n      if( near ){\n        near.activate();\n        near.trigger( cxtEvt );\n\n        r.hoverData.down = near;\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      r.hoverData.downTime = (new Date()).getTime();\n      r.hoverData.cxtDragged = false;\n\n    // Primary button\n    } else if (e.which == 1) {\n\n      if( near ){\n        near.activate();\n      }\n\n      // Element dragging\n      {\n        // If something is under the cursor and it is draggable, prepare to grab it\n        if (near != null) {\n\n          if( r.nodeIsDraggable(near) ){\n\n            var grabEvent = Event(e, {\n              type: 'grab',\n              cyPosition: { x: pos[0], y: pos[1] }\n            });\n\n            if ( near.isNode() && !near.selected() ){\n\n              draggedElements = r.dragData.possibleDragElements = [];\n              addNodeToDrag( near, { addToList: draggedElements } );\n\n              near.trigger(grabEvent);\n\n            } else if ( near.isNode() && near.selected() ){\n              draggedElements = r.dragData.possibleDragElements = [  ];\n\n              var selectedNodes = cy.$(function(){ return this.isNode() && this.selected(); });\n\n              for( var i = 0; i < selectedNodes.length; i++ ){\n\n                // Only add this selected node to drag if it is draggable, eg. has nonzero opacity\n                if( r.nodeIsDraggable( selectedNodes[i] ) ){\n                  addNodeToDrag( selectedNodes[i], { addToList: draggedElements } );\n                }\n              }\n\n              near.trigger( grabEvent );\n            }\n\n            r.redrawHint('eles', true);\n            r.redrawHint('drag', true);\n\n          }\n\n        }\n\n        r.hoverData.down = near;\n        r.hoverData.downTime = (new Date()).getTime();\n      }\n\n      triggerEvents( near, ['mousedown', 'tapstart', 'vmousedown'], e, {\n        cyPosition: { x: pos[0], y: pos[1] }\n      } );\n\n      if ( near == null ) {\n        select[4] = 1;\n\n        r.data.bgActivePosistion = {\n          x: pos[0],\n          y: pos[1]\n        };\n\n        r.redrawHint('select', true);\n\n        r.redraw();\n      } else if( near.isEdge() ){\n        select[4] = 1; // for future pan\n      }\n\n      checkForTaphold();\n\n    }\n\n    // Initialize selection box coordinates\n    select[0] = select[2] = pos[0];\n    select[1] = select[3] = pos[1];\n\n  }, false);\n\n  r.registerBinding(window, 'mousemove', function(e) {\n    var preventDefault = false;\n    var capture = r.hoverData.capture;\n\n    // save cycles if mouse events aren't to be captured\n    if ( !capture ){\n      var containerPageCoords = r.findContainerClientCoords();\n\n      if (e.clientX > containerPageCoords[0] && e.clientX < containerPageCoords[0] + r.canvasWidth\n        && e.clientY > containerPageCoords[1] && e.clientY < containerPageCoords[1] + r.canvasHeight\n      ) {\n        // inside container bounds so OK\n      } else {\n        return;\n      }\n\n      var cyContainer = r.container;\n      var target = e.target;\n      var tParent = target.parentNode;\n      var containerIsTarget = false;\n\n      while( tParent ){\n        if( tParent === cyContainer ){\n          containerIsTarget = true;\n          break;\n        }\n\n        tParent = tParent.parentNode;\n      }\n\n      if( !containerIsTarget ){ return; } // if target is outisde cy container, then this event is not for us\n    }\n\n    var cy = r.cy;\n    var zoom = cy.zoom();\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n    var select = r.selection;\n\n    var near = null;\n    if( !r.hoverData.draggingEles ){\n      near = r.findNearestElement(pos[0], pos[1], true, false);\n    }\n    var last = r.hoverData.last;\n    var down = r.hoverData.down;\n\n    var disp = [pos[0] - select[2], pos[1] - select[3]];\n\n    var draggedElements = r.dragData.possibleDragElements;\n\n    var dx = select[2] - select[0];\n    var dx2 = dx * dx;\n    var dy = select[3] - select[1];\n    var dy2 = dy * dy;\n    var dist2 = dx2 + dy2;\n    var rdist2 = dist2 * zoom * zoom;\n\n    var multSelKeyDown = isMultSelKeyDown( e );\n\n    r.hoverData.tapholdCancelled = true;\n\n    var updateDragDelta = function(){\n      var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || [];\n\n      if( dragDelta.length === 0 ){\n        dragDelta.push( disp[0] );\n        dragDelta.push( disp[1] );\n      } else {\n        dragDelta[0] += disp[0];\n        dragDelta[1] += disp[1];\n      }\n    };\n\n\n    preventDefault = true;\n\n    triggerEvents( near, ['mousemove', 'vmousemove', 'tapdrag'], e, {\n      cyPosition: { x: pos[0], y: pos[1] }\n    } );\n\n    // trigger context drag if rmouse down\n    if( r.hoverData.which === 3 ){\n      var cxtEvt = Event(e, {\n        type: 'cxtdrag',\n        cyPosition: { x: pos[0], y: pos[1] }\n      });\n\n      if( down ){\n        down.trigger( cxtEvt );\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      r.hoverData.cxtDragged = true;\n\n      if( !r.hoverData.cxtOver || near !== r.hoverData.cxtOver ){\n\n        if( r.hoverData.cxtOver ){\n          r.hoverData.cxtOver.trigger( Event(e, {\n            type: 'cxtdragout',\n            cyPosition: { x: pos[0], y: pos[1] }\n          }) );\n        }\n\n        r.hoverData.cxtOver = near;\n\n        if( near ){\n          near.trigger( Event(e, {\n            type: 'cxtdragover',\n            cyPosition: { x: pos[0], y: pos[1] }\n          }) );\n        }\n\n      }\n\n    // Check if we are drag panning the entire graph\n    } else if (r.hoverData.dragging) {\n      preventDefault = true;\n\n      if( cy.panningEnabled() && cy.userPanningEnabled() ){\n        var deltaP;\n\n        if( r.hoverData.justStartedPan ){\n          var mdPos = r.hoverData.mdownPos;\n\n          deltaP = {\n            x: ( pos[0] - mdPos[0] ) * zoom,\n            y: ( pos[1] - mdPos[1] ) * zoom\n          };\n\n          r.hoverData.justStartedPan = false;\n\n        } else {\n          deltaP = {\n            x: disp[0] * zoom,\n            y: disp[1] * zoom\n          };\n\n        }\n\n        cy.panBy( deltaP );\n\n        r.hoverData.dragged = true;\n      }\n\n      // Needs reproject due to pan changing viewport\n      pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n    // Checks primary button down & out of time & mouse not moved much\n    } else if(\n        select[4] == 1 && (down == null || down.isEdge())\n    ){\n\n      if( !r.hoverData.dragging && cy.boxSelectionEnabled() && ( multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled() ) ){\n        r.data.bgActivePosistion = undefined;\n        r.hoverData.selecting = true;\n\n        r.redrawHint('select', true);\n        r.redraw();\n\n      } else if( !r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled() ){\n        r.hoverData.dragging = true;\n        r.hoverData.justStartedPan = true;\n        select[4] = 0;\n\n        r.data.bgActivePosistion = {\n          x: pos[0],\n          y: pos[1]\n        };\n\n        r.redrawHint('select', true);\n        r.redraw();\n      }\n\n      if( down && down.isEdge() && down.active() ){ down.unactivate(); }\n\n    } else {\n      if( down && down.isEdge() && down.active() ){ down.unactivate(); }\n\n      if (near != last) {\n\n        if (last) {\n          triggerEvents( last, ['mouseout', 'tapdragout'], e, {\n            cyPosition: { x: pos[0], y: pos[1] }\n          } );\n        }\n\n        if (near) {\n          triggerEvents( near, ['mouseover', 'tapdragover'], e, {\n            cyPosition: { x: pos[0], y: pos[1] }\n          } );\n        }\n\n        r.hoverData.last = near;\n      }\n\n      if( down && down.isNode() && r.nodeIsDraggable(down) ){\n\n        if( rdist2 >= r.desktopTapThreshold2 ){ // then drag\n\n          var justStartedDrag = !r.dragData.didDrag;\n\n          if( justStartedDrag ) {\n            r.redrawHint('eles', true);\n          }\n\n          r.dragData.didDrag = true; // indicate that we actually did drag the node\n\n          var toTrigger = [];\n\n          for( var i = 0; i < draggedElements.length; i++ ){\n            var dEle = draggedElements[i];\n\n            // now, add the elements to the drag layer if not done already\n            if( !r.hoverData.draggingEles ){\n              addNodeToDrag( dEle, { inDragLayer: true } );\n            }\n\n            // Locked nodes not draggable, as well as non-visible nodes\n            if( dEle.isNode() && r.nodeIsDraggable(dEle) && dEle.grabbed() ){\n              var dPos = dEle._private.position;\n\n              toTrigger.push( dEle );\n\n              if( is.number(disp[0]) && is.number(disp[1]) ){\n                var updatePos = !dEle.isParent();\n\n                if( updatePos ){\n                  dPos.x += disp[0];\n                  dPos.y += disp[1];\n                }\n\n                if( justStartedDrag ){\n                  var dragDelta = r.hoverData.dragDelta;\n\n                  if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){\n                    dPos.x += dragDelta[0];\n                    dPos.y += dragDelta[1];\n                  }\n                }\n              }\n\n            }\n          }\n\n          r.hoverData.draggingEles = true;\n\n          var tcol = (Collection(cy, toTrigger));\n\n          tcol.updateCompoundBounds();\n          tcol.trigger('position drag');\n\n          r.redrawHint('drag', true);\n          r.redraw();\n\n        } else { // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant\n          updateDragDelta();\n        }\n      }\n\n      // prevent the dragging from triggering text selection on the page\n      preventDefault = true;\n    }\n\n    select[2] = pos[0]; select[3] = pos[1];\n\n    if( preventDefault ){\n      if(e.stopPropagation) e.stopPropagation();\n        if(e.preventDefault) e.preventDefault();\n        return false;\n      }\n  }, false);\n\n  r.registerBinding(window, 'mouseup', function(e) {\n    var capture = r.hoverData.capture;\n    if (!capture) { return; }\n    r.hoverData.capture = false;\n\n    var cy = r.cy; var pos = r.projectIntoViewport(e.clientX, e.clientY); var select = r.selection;\n    var near = r.findNearestElement(pos[0], pos[1], true, false);\n    var draggedElements = r.dragData.possibleDragElements; var down = r.hoverData.down;\n    var multSelKeyDown = isMultSelKeyDown( e );\n\n    if( r.data.bgActivePosistion ){\n      r.redrawHint('select', true);\n      r.redraw();\n    }\n\n    r.hoverData.tapholdCancelled = true;\n\n    r.data.bgActivePosistion = undefined; // not active bg now\n\n    if( down ){\n      down.unactivate();\n    }\n\n    if( r.hoverData.which === 3 ){\n      var cxtEvt = Event(e, {\n        type: 'cxttapend',\n        cyPosition: { x: pos[0], y: pos[1] }\n      });\n\n      if( down ){\n        down.trigger( cxtEvt );\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      if( !r.hoverData.cxtDragged ){\n        var cxtTap = Event(e, {\n          type: 'cxttap',\n          cyPosition: { x: pos[0], y: pos[1] }\n        });\n\n        if( down ){\n          down.trigger( cxtTap );\n        } else {\n          cy.trigger( cxtTap );\n        }\n      }\n\n      r.hoverData.cxtDragged = false;\n      r.hoverData.which = null;\n\n    } else if( r.hoverData.which === 1 ) {\n\n      // Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something\n      if ( (down == null) // not mousedown on node\n        && !r.dragData.didDrag // didn't move the node around\n        && !r.hoverData.selecting // not box selection\n        && !r.hoverData.dragged // didn't pan\n        && !isMultSelKeyDown( e )\n      ) {\n\n        cy.$(function(){\n          return this.selected();\n        }).unselect();\n\n        if (draggedElements.length > 0) {\n          r.redrawHint('eles', true);\n        }\n\n        r.dragData.possibleDragElements = draggedElements = [];\n      }\n\n      triggerEvents( near, ['mouseup', 'tapend', 'vmouseup'], e, {\n        cyPosition: { x: pos[0], y: pos[1] }\n      } );\n\n      if(\n        !r.dragData.didDrag // didn't move a node around\n        && !r.hoverData.dragged // didn't pan\n      ){\n        triggerEvents( near, ['click', 'tap', 'vclick'], e, {\n          cyPosition: { x: pos[0], y: pos[1] }\n        } );\n      }\n\n      // Single selection\n      if( near == down && !r.dragData.didDrag && !r.hoverData.selecting ){\n        if( near != null && near._private.selectable ){\n\n          if( r.hoverData.dragging ){\n            // if panning, don't change selection state\n          } else if( cy.selectionType() === 'additive' || multSelKeyDown ){\n            if( near.selected() ){\n              near.unselect();\n            } else {\n              near.select();\n            }\n          } else {\n            if( !multSelKeyDown ){\n              cy.$(':selected').unmerge( near ).unselect();\n              near.select();\n            }\n          }\n\n          r.redrawHint('eles', true);\n        }\n      }\n\n      if ( r.hoverData.selecting ) {\n        var newlySelected = [];\n        var box = r.getAllInBox( select[0], select[1], select[2], select[3] );\n\n        r.redrawHint('select', true);\n\n        if( box.length > 0 ) {\n          r.redrawHint('eles', true);\n        }\n\n        for( var i = 0; i < box.length; i++ ){\n          if( box[i]._private.selectable ){\n            newlySelected.push( box[i] );\n          }\n        }\n\n        var newlySelCol = Collection( cy, newlySelected );\n\n        if( cy.selectionType() === 'additive' ){\n          newlySelCol.select();\n        } else {\n          if( !multSelKeyDown ){\n            cy.$(':selected').unmerge( newlySelCol ).unselect();\n          }\n\n          newlySelCol.select();\n        }\n\n        // always need redraw in case eles unselectable\n        r.redraw();\n\n      }\n\n      // Cancel drag pan\n      if( r.hoverData.dragging ){\n        r.hoverData.dragging = false;\n\n        r.redrawHint('select', true);\n        r.redrawHint('eles', true);\n\n        r.redraw();\n      }\n\n      if (!select[4]) {\n\n\n        r.redrawHint('drag', true);\n        r.redrawHint('eles', true);\n\n        freeDraggedElements( draggedElements );\n\n        if( down ){ down.trigger('free'); }\n      }\n\n    } // else not right mouse\n\n    select[4] = 0; r.hoverData.down = null;\n\n    r.hoverData.cxtStarted = false;\n    r.hoverData.draggingEles = false;\n    r.hoverData.selecting = false;\n    r.dragData.didDrag = false;\n    r.hoverData.dragged = false;\n    r.hoverData.dragDelta = [];\n\n  }, false);\n\n  var wheelHandler = function(e) {\n\n\n    if( r.scrollingPage ){ return; } // while scrolling, ignore wheel-to-zoom\n\n    var cy = r.cy;\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n    var rpos = [pos[0] * cy.zoom() + cy.pan().x,\n                  pos[1] * cy.zoom() + cy.pan().y];\n\n    if( r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection() ){ // if pan dragging or cxt dragging, wheel movements make no zoom\n      e.preventDefault();\n      return;\n    }\n\n    if( cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled() ){\n      e.preventDefault();\n\n      r.data.wheelZooming = true;\n      clearTimeout( r.data.wheelTimeout );\n      r.data.wheelTimeout = setTimeout(function(){\n        r.data.wheelZooming = false;\n\n        r.redrawHint('eles', true);\n        r.redraw();\n      }, 150);\n\n      var diff = e.deltaY / -250 || e.wheelDeltaY / 1000 || e.wheelDelta / 1000;\n      diff = diff * r.wheelSensitivity;\n\n      var needsWheelFix = e.deltaMode === 1;\n      if( needsWheelFix ){ // fixes slow wheel events on ff/linux and ff/windows\n        diff *= 33;\n      }\n\n      cy.zoom({\n        level: cy.zoom() * Math.pow(10, diff),\n        renderedPosition: { x: rpos[0], y: rpos[1] }\n      });\n    }\n\n  };\n\n  // Functions to help with whether mouse wheel should trigger zooming\n  // --\n  r.registerBinding(r.container, 'wheel', wheelHandler, true);\n\n  // disable nonstandard wheel events\n  // r.registerBinding(r.container, 'mousewheel', wheelHandler, true);\n  // r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true);\n  // r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox\n\n  r.registerBinding(window, 'scroll', function(e){\n    r.scrollingPage = true;\n\n    clearTimeout( r.scrollingPageTimeout );\n    r.scrollingPageTimeout = setTimeout(function(){\n      r.scrollingPage = false;\n    }, 250);\n  }, true);\n\n  // Functions to help with handling mouseout/mouseover on the Cytoscape container\n        // Handle mouseout on Cytoscape container\n  r.registerBinding(r.container, 'mouseout', function(e) {\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n    r.cy.trigger(Event(e, {\n      type: 'mouseout',\n      cyPosition: { x: pos[0], y: pos[1] }\n    }));\n  }, false);\n\n  r.registerBinding(r.container, 'mouseover', function(e) {\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n    r.cy.trigger(Event(e, {\n      type: 'mouseover',\n      cyPosition: { x: pos[0], y: pos[1] }\n    }));\n  }, false);\n\n  var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom\n  var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom\n  var center1, modelCenter1; // center point on start pinch to zoom\n  var offsetLeft, offsetTop;\n  var containerWidth, containerHeight;\n  var twoFingersStartInside;\n\n  var distance = function(x1, y1, x2, y2){\n    return Math.sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );\n  };\n\n  var distanceSq = function(x1, y1, x2, y2){\n    return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);\n  };\n\n  var touchstartHandler;\n  r.registerBinding(r.container, 'touchstart', touchstartHandler = function(e) {\n    r.touchData.capture = true;\n    r.data.bgActivePosistion = undefined;\n\n    var cy = r.cy;\n    var nodes = r.getCachedNodes();\n    var edges = r.getCachedEdges();\n    var now = r.touchData.now;\n    var earlier = r.touchData.earlier;\n\n    if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n    if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n    if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n\n    // record starting points for pinch-to-zoom\n    if( e.touches[1] ){\n\n      // anything in the set of dragged eles should be released\n      var release = function( eles ){\n        for( var i = 0; i < eles.length; i++ ){\n          eles[i]._private.grabbed = false;\n          eles[i]._private.rscratch.inDragLayer = false;\n          if( eles[i].active() ){ eles[i].unactivate(); }\n        }\n      };\n      release(nodes);\n      release(edges);\n\n      var offsets = r.findContainerClientCoords();\n      offsetLeft = offsets[0];\n      offsetTop = offsets[1];\n      containerWidth = offsets[2];\n      containerHeight = offsets[3];\n\n      f1x1 = e.touches[0].clientX - offsetLeft;\n      f1y1 = e.touches[0].clientY - offsetTop;\n\n      f2x1 = e.touches[1].clientX - offsetLeft;\n      f2y1 = e.touches[1].clientY - offsetTop;\n\n      twoFingersStartInside =\n           0 <= f1x1 && f1x1 <= containerWidth\n        && 0 <= f2x1 && f2x1 <= containerWidth\n        && 0 <= f1y1 && f1y1 <= containerHeight\n        && 0 <= f2y1 && f2y1 <= containerHeight\n      ;\n\n      var pan = cy.pan();\n      var zoom = cy.zoom();\n\n      distance1 = distance( f1x1, f1y1, f2x1, f2y1 );\n      distance1Sq = distanceSq( f1x1, f1y1, f2x1, f2y1 );\n      center1 = [ (f1x1 + f2x1)/2, (f1y1 + f2y1)/2 ];\n      modelCenter1 = [\n        (center1[0] - pan.x) / zoom,\n        (center1[1] - pan.y) / zoom\n      ];\n\n      // consider context tap\n      var cxtDistThreshold = 200;\n      var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold;\n      if( distance1Sq < cxtDistThresholdSq && !e.touches[2] ){\n\n        var near1 = r.findNearestElement(now[0], now[1], true, true);\n        var near2 = r.findNearestElement(now[2], now[3], true, true);\n\n        if( near1 && near1.isNode() ){\n          near1.activate().trigger( Event(e, {\n            type: 'cxttapstart',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n          r.touchData.start = near1;\n\n        } else if( near2 && near2.isNode() ){\n          near2.activate().trigger( Event(e, {\n            type: 'cxttapstart',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n          r.touchData.start = near2;\n\n        } else {\n          cy.trigger( Event(e, {\n            type: 'cxttapstart',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n          r.touchData.start = null;\n        }\n\n        if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n        r.touchData.cxt = true;\n        r.touchData.cxtDragged = false;\n        r.data.bgActivePosistion = undefined;\n\n        r.redraw();\n        return;\n\n      }\n\n    }\n\n    if (e.touches[2]) {\n\n    } else if (e.touches[1]) {\n\n    } else if (e.touches[0]) {\n      var near = r.findNearestElement(now[0], now[1], true, true);\n\n      if (near != null) {\n        near.activate();\n\n        r.touchData.start = near;\n\n        if( near.isNode() && r.nodeIsDraggable(near) ){\n\n          var draggedEles = r.dragData.touchDragEles = [];\n\n          r.redrawHint('eles', true);\n          r.redrawHint('drag', true);\n\n          if( near.selected() ){\n            // reset drag elements, since near will be added again\n\n            var selectedNodes = cy.$(function(){\n              return this.isNode() && this.selected();\n            });\n\n            for( var k = 0; k < selectedNodes.length; k++ ){\n              var selectedNode = selectedNodes[k];\n\n              if( r.nodeIsDraggable(selectedNode) ){\n                addNodeToDrag( selectedNode, { addToList: draggedEles } );\n              }\n            }\n          } else {\n            addNodeToDrag( near, { addToList: draggedEles } );\n          }\n\n          near.trigger( Event(e, {\n            type: 'grab',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n        }\n      }\n\n      triggerEvents( near, ['touchstart', 'tapstart', 'vmousedown'], e, {\n        cyPosition: { x: now[0], y: now[1] }\n      } );\n\n      if (near == null) {\n        r.data.bgActivePosistion = {\n          x: pos[0],\n          y: pos[1]\n        };\n\n        r.redrawHint('select', true);\n        r.redraw();\n      }\n\n\n      // Tap, taphold\n      // -----\n\n      for (var i=0; i<now.length; i++) {\n        earlier[i] = now[i];\n        r.touchData.startPosition[i] = now[i];\n      }\n\n      r.touchData.singleTouchMoved = false;\n      r.touchData.singleTouchStartTime = +new Date();\n\n      clearTimeout( r.touchData.tapholdTimeout );\n      r.touchData.tapholdTimeout = setTimeout(function() {\n        if(\n            r.touchData.singleTouchMoved === false\n            && !r.pinching // if pinching, then taphold unselect shouldn't take effect\n        ){\n          triggerEvents( r.touchData.start, ['taphold'], e, {\n            cyPosition: { x: now[0], y: now[1] }\n          } );\n\n          if (!r.touchData.start) {\n            cy.$(':selected').unselect();\n          }\n\n        }\n      }, r.tapholdDuration);\n    }\n\n  }, false);\n\n  var touchmoveHandler;\n  r.registerBinding(window, 'touchmove', touchmoveHandler = function(e) {\n\n    var select = r.selection;\n    var capture = r.touchData.capture;\n    var cy = r.cy;\n    var now = r.touchData.now; var earlier = r.touchData.earlier;\n    var zoom = cy.zoom();\n\n    if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n    if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n    if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n    var disp = []; for (var j=0;j<now.length;j++) { disp[j] = now[j] - earlier[j]; }\n    var startPos = r.touchData.startPosition;\n    var dx = now[0] - startPos[0];\n    var dx2 = dx * dx;\n    var dy = now[1] - startPos[1];\n    var dy2 = dy * dy;\n    var dist2 = dx2 + dy2;\n    var rdist2 = dist2 * zoom * zoom;\n\n    // context swipe cancelling\n    if( capture && r.touchData.cxt ){\n      e.preventDefault();\n\n      var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop;\n      var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop;\n      // var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );\n      var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );\n      var factorSq = distance2Sq / distance1Sq;\n\n      var distThreshold = 150;\n      var distThresholdSq = distThreshold * distThreshold;\n      var factorThreshold = 1.5;\n      var factorThresholdSq = factorThreshold * factorThreshold;\n\n      // cancel ctx gestures if the distance b/t the fingers increases\n      if( factorSq >= factorThresholdSq || distance2Sq >= distThresholdSq ){\n        r.touchData.cxt = false;\n        if( r.touchData.start ){ r.touchData.start.unactivate(); r.touchData.start = null; }\n        r.data.bgActivePosistion = undefined;\n        r.redrawHint('select', true);\n\n        var cxtEvt = Event(e, {\n          type: 'cxttapend',\n          cyPosition: { x: now[0], y: now[1] }\n        });\n        if( r.touchData.start ){\n          r.touchData.start.trigger( cxtEvt );\n        } else {\n          cy.trigger( cxtEvt );\n        }\n      }\n\n    }\n\n    // context swipe\n    if( capture && r.touchData.cxt ){\n      var cxtEvt = Event(e, {\n        type: 'cxtdrag',\n        cyPosition: { x: now[0], y: now[1] }\n      });\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n\n      if( r.touchData.start ){\n        r.touchData.start.trigger( cxtEvt );\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n      r.touchData.cxtDragged = true;\n\n      var near = r.findNearestElement(now[0], now[1], true, true);\n\n      if( !r.touchData.cxtOver || near !== r.touchData.cxtOver ){\n\n        if( r.touchData.cxtOver ){\n          r.touchData.cxtOver.trigger( Event(e, {\n            type: 'cxtdragout',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n        }\n\n        r.touchData.cxtOver = near;\n\n        if( near ){\n          near.trigger( Event(e, {\n            type: 'cxtdragover',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n\n        }\n\n      }\n\n    // box selection\n    } else if( capture && e.touches[2] && cy.boxSelectionEnabled() ){\n      e.preventDefault();\n\n      r.data.bgActivePosistion = undefined;\n\n      this.lastThreeTouch = +new Date();\n      r.touchData.selecting = true;\n\n      r.redrawHint('select', true);\n\n      if( !select || select.length === 0 || select[0] === undefined ){\n        select[0] = (now[0] + now[2] + now[4])/3;\n        select[1] = (now[1] + now[3] + now[5])/3;\n        select[2] = (now[0] + now[2] + now[4])/3 + 1;\n        select[3] = (now[1] + now[3] + now[5])/3 + 1;\n      } else {\n        select[2] = (now[0] + now[2] + now[4])/3;\n        select[3] = (now[1] + now[3] + now[5])/3;\n      }\n\n      select[4] = 1;\n      r.touchData.selecting = true;\n\n      r.redraw();\n\n    // pinch to zoom\n    } else if ( capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled() ) { // two fingers => pinch to zoom\n      e.preventDefault();\n\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n\n      var draggedEles = r.dragData.touchDragEles;\n      if( draggedEles ){\n        r.redrawHint('drag', true);\n\n        for( var i = 0; i < draggedEles.length; i++ ){\n          draggedEles[i]._private.grabbed = false;\n          draggedEles[i]._private.rscratch.inDragLayer = false;\n        }\n      }\n\n      // (x2, y2) for fingers 1 and 2\n      var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop;\n      var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop;\n\n\n      var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );\n      // var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );\n      // var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq );\n      var factor = distance2 / distance1;\n\n      if( factor != 1 && twoFingersStartInside){\n        // delta finger1\n        var df1x = f1x2 - f1x1;\n        var df1y = f1y2 - f1y1;\n\n        // delta finger 2\n        var df2x = f2x2 - f2x1;\n        var df2y = f2y2 - f2y1;\n\n        // translation is the normalised vector of the two fingers movement\n        // i.e. so pinching cancels out and moving together pans\n        var tx = (df1x + df2x)/2;\n        var ty = (df1y + df2y)/2;\n\n        // adjust factor by the speed multiplier\n        // var speed = 1.5;\n        // if( factor > 1 ){\n        //   factor = (factor - 1) * speed + 1;\n        // } else {\n        //   factor = 1 - (1 - factor) * speed;\n        // }\n\n        // now calculate the zoom\n        var zoom1 = cy.zoom();\n        var zoom2 = zoom1 * factor;\n        var pan1 = cy.pan();\n\n        // the model center point converted to the current rendered pos\n        var ctrx = modelCenter1[0] * zoom1 + pan1.x;\n        var ctry = modelCenter1[1] * zoom1 + pan1.y;\n\n        var pan2 = {\n          x: -zoom2/zoom1 * (ctrx - pan1.x - tx) + ctrx,\n          y: -zoom2/zoom1 * (ctry - pan1.y - ty) + ctry\n        };\n\n        // remove dragged eles\n        if( r.touchData.start ){\n          var draggedEles = r.dragData.touchDragEles;\n\n          if( draggedEles ){ for( var i = 0; i < draggedEles.length; i++ ){\n            var dEi_p = draggedEles[i]._private;\n\n            dEi_p.grabbed = false;\n            dEi_p.rscratch.inDragLayer = false;\n          } }\n\n          var start_p = r.touchData.start._private;\n          start_p.active = false;\n          start_p.grabbed = false;\n          start_p.rscratch.inDragLayer = false;\n\n          r.redrawHint('drag', true);\n\n          r.touchData.start\n            .trigger('free')\n            .trigger('unactivate')\n          ;\n        }\n\n        cy.viewport({\n          zoom: zoom2,\n          pan: pan2,\n          cancelOnFailedZoom: true\n        });\n\n        distance1 = distance2;\n        f1x1 = f1x2;\n        f1y1 = f1y2;\n        f2x1 = f2x2;\n        f2y1 = f2y2;\n\n        r.pinching = true;\n      }\n\n      // Re-project\n      if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n      if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n      if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n    } else if (e.touches[0]) {\n      var start = r.touchData.start;\n      var last = r.touchData.last;\n      var near = near || r.findNearestElement(now[0], now[1], true, true);\n\n      if( start != null ){\n        e.preventDefault();\n      }\n\n      // dragging nodes\n      if( start != null && start._private.group == 'nodes' && r.nodeIsDraggable(start) ){\n\n        if( rdist2 >= r.touchTapThreshold2 ){ // then dragging can happen\n          var draggedEles = r.dragData.touchDragEles;\n          var justStartedDrag = !r.dragData.didDrag;\n\n          for( var k = 0; k < draggedEles.length; k++ ){\n            var draggedEle = draggedEles[k];\n\n            if( justStartedDrag ){\n              addNodeToDrag( draggedEle, { inDragLayer: true } );\n            }\n\n            if( r.nodeIsDraggable(draggedEle) && draggedEle.isNode() && draggedEle.grabbed() ){\n              r.dragData.didDrag = true;\n              var dPos = draggedEle._private.position;\n              var updatePos = !draggedEle.isParent();\n\n              if( updatePos && is.number(disp[0]) && is.number(disp[1]) ){\n                dPos.x += disp[0];\n                dPos.y += disp[1];\n              }\n\n              if( justStartedDrag ){\n                r.redrawHint('eles', true);\n\n                var dragDelta = r.touchData.dragDelta;\n\n                if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){\n                  dPos.x += dragDelta[0];\n                  dPos.y += dragDelta[1];\n                }\n\n              }\n            }\n          }\n\n          var tcol = Collection(cy, draggedEles);\n\n          tcol.updateCompoundBounds();\n          tcol.trigger('position drag');\n\n          r.hoverData.draggingEles = true;\n\n          r.redrawHint('drag', true);\n\n          if(\n               r.touchData.startPosition[0] == earlier[0]\n            && r.touchData.startPosition[1] == earlier[1]\n          ){\n\n            r.redrawHint('eles', true);\n          }\n\n          r.redraw();\n        } else { // otherise keep track of drag delta for later\n          var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || [];\n\n          if( dragDelta.length === 0 ){\n            dragDelta.push( disp[0] );\n            dragDelta.push( disp[1] );\n          } else {\n            dragDelta[0] += disp[0];\n            dragDelta[1] += disp[1];\n          }\n        }\n      }\n\n      // touchmove\n      {\n        triggerEvents( (start || near), ['touchmove', 'tapdrag', 'vmousemove'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n\n        if (near != last) {\n          if (last) { last.trigger(Event(e, { type: 'tapdragout', cyPosition: { x: now[0], y: now[1] } })); }\n          if (near) { near.trigger(Event(e, { type: 'tapdragover', cyPosition: { x: now[0], y: now[1] } })); }\n        }\n\n        r.touchData.last = near;\n      }\n\n      // check to cancel taphold\n      for (var i=0;i<now.length;i++) {\n        if( now[i]\n          && r.touchData.startPosition[i]\n          && rdist2 > r.touchTapThreshold2 ){\n\n          r.touchData.singleTouchMoved = true;\n        }\n      }\n\n      // panning\n      if(\n          capture\n          && ( start == null || start.isEdge() )\n          && cy.panningEnabled() && cy.userPanningEnabled()\n      ){\n\n        e.preventDefault();\n\n        if( r.swipePanning ){\n          cy.panBy({\n            x: disp[0] * zoom,\n            y: disp[1] * zoom\n          });\n\n        } else if( rdist2 >= r.touchTapThreshold2 ){\n          r.swipePanning = true;\n\n          cy.panBy({\n            x: dx * zoom,\n            y: dy * zoom\n          });\n\n          if( start ){\n            start.unactivate();\n\n            if( !r.data.bgActivePosistion ){\n              r.data.bgActivePosistion = {\n                x: now[0],\n                y: now[1]\n              };\n            }\n\n            r.redrawHint('select', true);\n\n            r.touchData.start = null;\n          }\n        }\n\n        // Re-project\n        var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n        now[0] = pos[0]; now[1] = pos[1];\n      }\n    }\n\n    for (var j=0; j<now.length; j++) { earlier[j] = now[j]; }\n    //r.redraw();\n\n  }, false);\n\n  var touchcancelHandler;\n  r.registerBinding(window, 'touchcancel', touchcancelHandler = function(e) {\n    var start = r.touchData.start;\n\n    r.touchData.capture = false;\n\n    if( start ){\n      start.unactivate();\n    }\n  });\n\n  var touchendHandler;\n  r.registerBinding(window, 'touchend', touchendHandler = function(e) {\n    var start = r.touchData.start;\n\n    var capture = r.touchData.capture;\n\n    if( capture ){\n      r.touchData.capture = false;\n\n      e.preventDefault();\n    } else {\n      return;\n    }\n\n    var select = r.selection;\n\n    r.swipePanning = false;\n    r.hoverData.draggingEles = false;\n\n    var cy = r.cy;\n    var zoom = cy.zoom();\n    var now = r.touchData.now;\n    var earlier = r.touchData.earlier;\n\n    if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n    if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n    if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n    if( start ){\n      start.unactivate();\n    }\n\n    var ctxTapend;\n    if( r.touchData.cxt ){\n      ctxTapend = Event(e, {\n        type: 'cxttapend',\n        cyPosition: { x: now[0], y: now[1] }\n      });\n\n      if( start ){\n        start.trigger( ctxTapend );\n      } else {\n        cy.trigger( ctxTapend );\n      }\n\n      if( !r.touchData.cxtDragged ){\n        var ctxTap = Event(e, {\n          type: 'cxttap',\n          cyPosition: { x: now[0], y: now[1] }\n        });\n\n        if( start ){\n          start.trigger( ctxTap );\n        } else {\n          cy.trigger( ctxTap );\n        }\n\n      }\n\n      if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n      r.touchData.cxt = false;\n      r.touchData.start = null;\n\n      r.redraw();\n      return;\n    }\n\n    // no more box selection if we don't have three fingers\n    if( !e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting ){\n      r.touchData.selecting = false;\n\n      var newlySelected = [];\n      var box = r.getAllInBox( select[0], select[1], select[2], select[3] );\n\n      select[0] = undefined;\n      select[1] = undefined;\n      select[2] = undefined;\n      select[3] = undefined;\n      select[4] = 0;\n\n      r.redrawHint('select', true);\n\n      for( var i = 0; i< box.length; i++ ) {\n        if( box[i]._private.selectable ){\n          newlySelected.push( box[i] );\n        }\n      }\n\n      var newlySelCol = Collection( cy, newlySelected );\n\n      newlySelCol.select();\n\n      if( newlySelCol.length > 0 ) {\n        r.redrawHint('eles', true);\n      } else {\n        r.redraw();\n      }\n    }\n\n    var updateStartStyle = false;\n\n    if( start != null ){\n      start._private.active = false;\n      updateStartStyle = true;\n      start.unactivate();\n    }\n\n    if (e.touches[2]) {\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n    } else if (e.touches[1]) {\n\n    } else if (e.touches[0]) {\n\n    // Last touch released\n    } else if (!e.touches[0]) {\n\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n\n      var draggedEles = r.dragData.touchDragEles;\n\n      if (start != null ) {\n\n        var startWasGrabbed = start._private.grabbed;\n\n        freeDraggedElements( draggedEles );\n\n        r.redrawHint('drag', true);\n        r.redrawHint('eles', true);\n\n        if( startWasGrabbed ){\n          start.trigger('free');\n        }\n\n        triggerEvents( start, ['touchend', 'tapend', 'vmouseup'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n\n        start.unactivate();\n\n        r.touchData.start = null;\n\n      } else {\n        var near = r.findNearestElement(now[0], now[1], true, true);\n\n        triggerEvents( near, ['touchend', 'tapend', 'vmouseup'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n\n      }\n\n      var dx = r.touchData.startPosition[0] - now[0];\n      var dx2 = dx * dx;\n      var dy = r.touchData.startPosition[1] - now[1];\n      var dy2 = dy * dy;\n      var dist2 = dx2 + dy2;\n      var rdist2 = dist2 * zoom * zoom;\n\n      // Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance\n      if (start != null\n          && !r.dragData.didDrag // didn't drag nodes around\n          && start._private.selectable\n          && rdist2 < r.touchTapThreshold2\n          && !r.pinching // pinch to zoom should not affect selection\n      ) {\n\n        if( cy.selectionType() === 'single' ){\n          cy.$(':selected').unmerge( start ).unselect();\n          start.select();\n        } else {\n          if( start.selected() ){\n            start.unselect();\n          } else {\n            start.select();\n          }\n        }\n\n        updateStartStyle = true;\n\n\n        r.redrawHint('eles', true);\n      }\n\n      // Tap event, roughly same as mouse click event for touch\n      if( !r.touchData.singleTouchMoved ){\n        triggerEvents( start, ['tap', 'vclick'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n      }\n\n      r.touchData.singleTouchMoved = true;\n    }\n\n    for( var j = 0; j < now.length; j++ ){ earlier[j] = now[j]; }\n\n    r.dragData.didDrag = false; // reset for next mousedown\n\n    if( e.touches.length === 0 ){\n      r.touchData.dragDelta = [];\n    }\n\n    if( updateStartStyle && start ){\n      start.updateStyle(false);\n    }\n\n    if( e.touches.length < 2 ){\n      r.pinching = false;\n      r.redrawHint('eles', true);\n      r.redraw();\n    }\n\n    //r.redraw();\n\n  }, false);\n\n  // fallback compatibility layer for ms pointer events\n  if( typeof TouchEvent === 'undefined' ){\n\n    var pointers = [];\n\n    var makeTouch = function( e ){\n      return {\n        clientX: e.clientX,\n        clientY: e.clientY,\n        force: 1,\n        identifier: e.pointerId,\n        pageX: e.pageX,\n        pageY: e.pageY,\n        radiusX: e.width/2,\n        radiusY: e.height/2,\n        screenX: e.screenX,\n        screenY: e.screenY,\n        target: e.target\n      };\n    };\n\n    var makePointer = function( e ){\n      return {\n        event: e,\n        touch: makeTouch(e)\n      };\n    };\n\n    var addPointer = function( e ){\n      pointers.push( makePointer(e) );\n    };\n\n    var removePointer = function( e ){\n      for( var i = 0; i < pointers.length; i++ ){\n        var p = pointers[i];\n\n        if( p.event.pointerId === e.pointerId ){\n          pointers.splice( i, 1 );\n          return;\n        }\n      }\n    };\n\n    var updatePointer = function( e ){\n      var p = pointers.filter(function( p ){\n        return p.event.pointerId === e.pointerId;\n      })[0];\n\n      p.event = e;\n      p.touch = makeTouch(e);\n    };\n\n    var addTouchesToEvent = function( e ){\n      e.touches = pointers.map(function( p ){\n        return p.touch;\n      });\n    };\n\n    r.registerBinding(r.container, 'pointerdown', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      e.preventDefault();\n\n      addPointer( e );\n\n      addTouchesToEvent( e );\n      touchstartHandler( e );\n    });\n\n    r.registerBinding(r.container, 'pointerup', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      removePointer( e );\n\n      addTouchesToEvent( e );\n      touchendHandler( e );\n    });\n\n    r.registerBinding(r.container, 'pointercancel', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      removePointer( e );\n\n      addTouchesToEvent( e );\n      touchcancelHandler( e );\n    });\n\n    r.registerBinding(r.container, 'pointermove', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      e.preventDefault();\n\n      updatePointer( e );\n\n      addTouchesToEvent( e );\n      touchmoveHandler( e );\n    });\n\n  }\n};\n\nmodule.exports = BRp;\n\n},{\"../../../collection\":23,\"../../../event\":42,\"../../../is\":77,\"../../../util\":94}],60:[function(_dereq_,module,exports){\n'use strict';\n\nvar math = _dereq_('../../../math');\n\nvar BRp = {};\n\nBRp.registerNodeShapes = function(){\n  var nodeShapes = this.nodeShapes = {};\n  var renderer = this;\n\n  nodeShapes['ellipse'] = {\n    name: 'ellipse',\n\n    draw: function( context, centerX, centerY, width, height ){\n      renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );\n    },\n\n    intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n      return math.intersectLineEllipse(\n        x, y,\n        nodeX,\n        nodeY,\n        width / 2 + padding,\n        height / 2 + padding)\n      ;\n    },\n\n    checkPoint: function( x, y, padding, width, height, centerX, centerY ){\n      x -= centerX;\n      y -= centerY;\n\n      x /= (width / 2 + padding);\n      y /= (height / 2 + padding);\n\n      return x*x + y*y <= 1;\n    }\n  };\n\n  function generatePolygon( name, points ){\n    return ( nodeShapes[name] = {\n      name: name,\n\n      points: points,\n\n      draw: function( context, centerX, centerY, width, height ){\n        renderer.nodeShapeImpl('polygon')( context, centerX, centerY, width, height, this.points );\n      },\n\n      intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n        return math.polygonIntersectLine(\n            x, y,\n            this.points,\n            nodeX,\n            nodeY,\n            width / 2, height / 2,\n            padding)\n          ;\n      },\n\n      checkPoint: function( x, y, padding, width, height, centerX, centerY ){\n        return math.pointInsidePolygon(x, y, nodeShapes[name].points,\n          centerX, centerY, width, height, [0, -1], padding)\n        ;\n      }\n    } );\n  }\n\n  generatePolygon( 'triangle', math.generateUnitNgonPointsFitToSquare(3, 0) );\n\n  generatePolygon( 'square', math.generateUnitNgonPointsFitToSquare(4, 0) );\n  nodeShapes['rectangle'] = nodeShapes['square'];\n\n  nodeShapes['roundrectangle'] = {\n    name: 'roundrectangle',\n\n    points: math.generateUnitNgonPointsFitToSquare(4, 0),\n\n    draw: function( context, centerX, centerY, width, height ){\n      renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );\n    },\n\n    intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n      return math.roundRectangleIntersectLine(\n        x, y,\n        nodeX,\n        nodeY,\n        width, height,\n        padding)\n      ;\n    },\n\n    // Looks like the width passed into this function is actually the total width / 2\n    checkPoint: function(\n      x, y, padding, width, height, centerX, centerY ){\n\n      var cornerRadius = math.getRoundRectangleRadius(width, height);\n\n      // Check hBox\n      if (math.pointInsidePolygon(x, y, this.points,\n        centerX, centerY, width, height - 2 * cornerRadius, [0, -1], padding) ){\n        return true;\n      }\n\n      // Check vBox\n      if (math.pointInsidePolygon(x, y, this.points,\n        centerX, centerY, width - 2 * cornerRadius, height, [0, -1], padding) ){\n        return true;\n      }\n\n      var checkInEllipse = function( x, y, centerX, centerY, width, height, padding ){\n        x -= centerX;\n        y -= centerY;\n\n        x /= (width / 2 + padding);\n        y /= (height / 2 + padding);\n\n        return (x*x + y*y <= 1);\n      };\n\n\n      // Check top left quarter circle\n      if (checkInEllipse(x, y,\n        centerX - width / 2 + cornerRadius,\n        centerY - height / 2 + cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      // Check top right quarter circle\n      if (checkInEllipse(x, y,\n        centerX + width / 2 - cornerRadius,\n        centerY - height / 2 + cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      // Check bottom right quarter circle\n      if (checkInEllipse(x, y,\n        centerX + width / 2 - cornerRadius,\n        centerY + height / 2 - cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      // Check bottom left quarter circle\n      if (checkInEllipse(x, y,\n        centerX - width / 2 + cornerRadius,\n        centerY + height / 2 - cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      return false;\n    }\n  };\n\n  generatePolygon( 'diamond', [\n    0, 1,\n    1, 0,\n    0, -1,\n    -1, 0\n  ] );\n\n  generatePolygon( 'pentagon', math.generateUnitNgonPointsFitToSquare(5, 0) );\n\n  generatePolygon( 'hexagon', math.generateUnitNgonPointsFitToSquare(6, 0) );\n\n  generatePolygon( 'heptagon', math.generateUnitNgonPointsFitToSquare(7, 0) );\n\n  generatePolygon( 'octagon', math.generateUnitNgonPointsFitToSquare(8, 0) );\n\n  var star5Points = new Array(20);\n  {\n    var outerPoints = math.generateUnitNgonPoints(5, 0);\n    var innerPoints = math.generateUnitNgonPoints(5, Math.PI / 5);\n\n    // Outer radius is 1; inner radius of star is smaller\n    var innerRadius = 0.5 * (3 - Math.sqrt(5));\n    innerRadius *= 1.57;\n\n    for (var i=0;i<innerPoints.length/2;i++ ){\n      innerPoints[i*2] *= innerRadius;\n      innerPoints[i*2+1] *= innerRadius;\n    }\n\n    for (var i=0;i<20/4;i++ ){\n      star5Points[i*4] = outerPoints[i*2];\n      star5Points[i*4+1] = outerPoints[i*2+1];\n\n      star5Points[i*4+2] = innerPoints[i*2];\n      star5Points[i*4+3] = innerPoints[i*2+1];\n    }\n  }\n\n  star5Points = math.fitPolygonToSquare( star5Points );\n\n  generatePolygon( 'star', star5Points );\n\n  generatePolygon( 'vee', [\n    -1, -1,\n    0, -0.333,\n    1, -1,\n    0, 1\n  ] );\n\n  generatePolygon( 'rhomboid', [\n    -1, -1,\n    0.333, -1,\n    1, 1,\n    -0.333, 1\n  ] );\n\n  nodeShapes.makePolygon = function( points ){\n\n    // use caching on user-specified polygons so they are as fast as native shapes\n\n    var key = points.join('$');\n    var name = 'polygon-' + key;\n    var shape;\n\n    if( (shape = nodeShapes[name]) ){ // got cached shape\n      return shape;\n    }\n\n    // create and cache new shape\n    return generatePolygon( name, points );\n  };\n\n};\n\nmodule.exports = BRp;\n\n},{\"../../../math\":79}],61:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../../../util');\n\nvar BRp = {};\n\nBRp.timeToRender = function(){\n  return this.redrawTotalTime / this.redrawCount;\n};\n\nvar minRedrawLimit = 1000/60; // people can't see much better than 60fps\nvar maxRedrawLimit = 1000;  // don't cap max b/c it's more important to be responsive than smooth\n\nBRp.redraw = function( options ){\n  options = options || util.staticEmptyObject();\n\n  var r = this;\n  var forcedContext = options.forcedContext;\n\n  if( r.averageRedrawTime === undefined ){ r.averageRedrawTime = 0; }\n  if( r.lastRedrawTime === undefined ){ r.lastRedrawTime = 0; }\n\n  var redrawLimit = r.lastRedrawTime; // estimate the ideal redraw limit based on how fast we can draw\n  redrawLimit = minRedrawLimit > redrawLimit ? minRedrawLimit : redrawLimit;\n  redrawLimit = redrawLimit < maxRedrawLimit ? redrawLimit : maxRedrawLimit;\n\n  if( r.lastDrawTime === undefined ){ r.lastDrawTime = 0; }\n\n  var nowTime = Date.now();\n  var timeElapsed = nowTime - r.lastDrawTime;\n  var callAfterLimit = timeElapsed >= redrawLimit;\n\n  if( !forcedContext ){\n    if( !callAfterLimit || r.currentlyDrawing ){\n      r.skipFrame = true;\n      return;\n    }\n  }\n\n  r.requestedFrame = true;\n  r.currentlyDrawing = true;\n  r.renderOptions = options;\n};\n\nBRp.startRenderLoop = function(){\n  var r = this;\n\n  var renderFn = function(){\n    if( r.destroyed ){ return; }\n\n    if( r.requestedFrame && !r.skipFrame ){\n      var startTime = util.performanceNow();\n\n      r.render( r.renderOptions );\n\n      var endTime = r.lastRedrawTime = util.performanceNow();\n\n      if( r.averageRedrawTime === undefined ){\n        r.averageRedrawTime = endTime - startTime;\n      }\n\n      if( r.redrawCount === undefined ){\n        r.redrawCount = 0;\n      }\n\n      r.redrawCount++;\n\n      if( r.redrawTotalTime === undefined ){\n        r.redrawTotalTime = 0;\n      }\n\n      var duration = endTime - startTime;\n\n      r.redrawTotalTime += duration;\n      r.lastRedrawTime = duration;\n\n      // use a weighted average with a bias from the previous average so we don't spike so easily\n      r.averageRedrawTime = r.averageRedrawTime/2 + duration/2;\n\n      r.requestedFrame = false;\n    }\n\n    r.skipFrame = false;\n\n    util.requestAnimationFrame( renderFn );\n  };\n\n  util.requestAnimationFrame( renderFn );\n\n};\n\nmodule.exports = BRp;\n\n},{\"../../../util\":94}],62:[function(_dereq_,module,exports){\n'use strict';\n\nvar CRp = {};\n\nvar impl;\n\nCRp.arrowShapeImpl = function( name ){\n  return ( impl || (impl = {\n    'polygon': function( context, points ){\n      for( var i = 0; i < points.length; i++ ){\n        var pt = points[i];\n\n        context.lineTo( pt.x, pt.y );\n      }\n    },\n\n    'triangle-backcurve': function( context, points, controlPoint ){\n      var firstPt;\n\n      for( var i = 0; i < points.length; i++ ){\n        var pt = points[i];\n\n        if( i === 0 ){\n          firstPt = pt;\n        }\n\n        context.lineTo( pt.x, pt.y );\n      }\n\n      context.quadraticCurveTo( controlPoint.x, controlPoint.y, firstPt.x, firstPt.y );\n    },\n\n    'triangle-tee': function( context, trianglePoints, teePoints ){\n      var triPts = trianglePoints;\n      for( var i = 0; i < triPts.length; i++ ){\n        var pt = triPts[i];\n\n        context.lineTo( pt.x, pt.y );\n      }\n\n      var teePts = teePoints;\n      var firstTeePt = teePoints[0];\n      context.moveTo( firstTeePt.x, firstTeePt.y );\n\n      for( var i = 0; i < teePts.length; i++ ){\n        var pt = teePts[i];\n\n        context.lineTo( pt.x, pt.y );\n      }\n    },\n\n    'circle': function( context, rx, ry, r ){\n      context.arc(rx, ry, r, 0, Math.PI * 2, false);\n    }\n  }) )[ name ];\n};\n\nmodule.exports = CRp;\n\n},{}],63:[function(_dereq_,module,exports){\n'use strict';\n\nvar CRp = {};\n\nCRp.drawEdge = function(context, edge, drawOverlayInstead) {\n  var rs = edge._private.rscratch;\n  var usePaths = this.usePaths();\n\n  // if bezier ctrl pts can not be calculated, then die\n  if( rs.badBezier || rs.badLine || isNaN( rs.allpts[0] ) ){ // iNaN in case edge is impossible and browser bugs (e.g. safari)\n    return;\n  }\n\n  var style = edge._private.style;\n\n  // Edge line width\n  if (style['width'].pfValue <= 0) {\n    return;\n  }\n\n  var overlayPadding = style['overlay-padding'].pfValue;\n  var overlayOpacity = style['overlay-opacity'].value;\n  var overlayColor = style['overlay-color'].value;\n\n  // Edge color & opacity\n  if( drawOverlayInstead ){\n\n    if( overlayOpacity === 0 ){ // exit early if no overlay\n      return;\n    }\n\n    this.strokeStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n    context.lineCap = 'round';\n\n    if( rs.edgeType == 'self' && !usePaths ){\n      context.lineCap = 'butt';\n    }\n\n  } else {\n    var lineColor = style['line-color'].value;\n\n    this.strokeStyle(context, lineColor[0], lineColor[1], lineColor[2], style.opacity.value);\n\n    context.lineCap = 'butt';\n  }\n\n  var edgeWidth = style['width'].pfValue + (drawOverlayInstead ? 2 * overlayPadding : 0);\n  var lineStyle = drawOverlayInstead ? 'solid' : style['line-style'].value;\n  context.lineWidth = edgeWidth;\n\n  var shadowBlur = style['shadow-blur'].pfValue;\n  var shadowOpacity = style['shadow-opacity'].value;\n  var shadowColor = style['shadow-color'].value;\n  var shadowOffsetX = style['shadow-offset-x'].pfValue;\n  var shadowOffsetY = style['shadow-offset-y'].pfValue;\n\n  this.shadowStyle(context,  shadowColor, drawOverlayInstead ? 0 : shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n  this.drawEdgePath(\n    edge,\n    context,\n    rs.allpts,\n    lineStyle,\n    edgeWidth\n  );\n\n  this.drawArrowheads(context, edge, drawOverlayInstead);\n\n  this.shadowStyle(context, 'transparent', 0); // reset for next guy\n\n};\n\n\nCRp.drawEdgePath = function(edge, context, pts, type, width) {\n  var rs = edge._private.rscratch;\n  var canvasCxt = context;\n  var path;\n  var pathCacheHit = false;\n  var usePaths = this.usePaths();\n\n  if( usePaths ){\n    var pathCacheKey = pts.join('$');\n    var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey;\n\n    if( keyMatches ){\n      path = context = rs.pathCache;\n      pathCacheHit = true;\n    } else {\n      path = context = new Path2D();\n      rs.pathCacheKey = pathCacheKey;\n      rs.pathCache = path;\n    }\n  }\n\n  if( canvasCxt.setLineDash ){ // for very outofdate browsers\n    switch( type ){\n      case 'dotted':\n        canvasCxt.setLineDash([ 1, 1 ]);\n        break;\n\n      case 'dashed':\n        canvasCxt.setLineDash([ 6, 3 ]);\n        break;\n\n      case 'solid':\n        canvasCxt.setLineDash([ ]);\n        break;\n    }\n  }\n\n  if( !pathCacheHit ){\n    if( context.beginPath ){ context.beginPath(); }\n    context.moveTo( pts[0], pts[1] );\n\n    switch( rs.edgeType ){\n      case 'bezier':\n      case 'self':\n      case 'compound':\n      case 'multibezier':\n        if( !rs.badBezier ){\n          for( var i = 2; i + 3 < pts.length; i += 4 ){\n            context.quadraticCurveTo( pts[i], pts[i+1], pts[i+2], pts[i+3] );\n          }\n        }\n        break;\n\n      case 'straight':\n      case 'segments':\n      case 'haystack':\n        if( !rs.badLine ){\n          for( var i = 2; i + 1 < pts.length; i += 2 ){\n            context.lineTo( pts[i], pts[i+1] );\n          }\n        }\n        break;\n    }\n  }\n\n  context = canvasCxt;\n  if( usePaths ){\n    context.stroke( path );\n  } else {\n    context.stroke();\n  }\n\n  // reset any line dashes\n  if( context.setLineDash ){ // for very outofdate browsers\n    context.setLineDash([ ]);\n  }\n\n};\n\nCRp.drawArrowheads = function(context, edge, drawOverlayInstead) {\n  if( drawOverlayInstead ){ return; } // don't do anything for overlays\n\n  var rs = edge._private.rscratch;\n  var isHaystack = rs.edgeType === 'haystack';\n\n  if( !isHaystack ){\n    this.drawArrowhead( context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle );\n  }\n\n  this.drawArrowhead( context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle );\n\n  this.drawArrowhead( context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle );\n\n  if( !isHaystack ){\n    this.drawArrowhead( context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle );\n  }\n};\n\nCRp.drawArrowhead = function( context, edge, prefix, x, y, angle ){\n  if( isNaN(x) || x == null || isNaN(y) || y == null || isNaN(angle) || angle == null ){ return; }\n\n  var self = this;\n  var style = edge._private.style;\n  var arrowShape = style[prefix + '-arrow-shape'].value;\n\n  if( arrowShape === 'none' ){\n    return;\n  }\n\n  var gco = context.globalCompositeOperation;\n\n  var arrowClearFill = style[prefix + '-arrow-fill'].value === 'hollow' ? 'both' : 'filled';\n  var arrowFill = style[prefix + '-arrow-fill'].value;\n\n  if( arrowShape === 'half-triangle-overshot' ){\n    arrowFill = 'hollow';\n    arrowClearFill = 'hollow';\n  }\n\n  if( style.opacity.value !== 1 || arrowFill === 'hollow' ){ // then extra clear is needed\n    context.globalCompositeOperation = 'destination-out';\n\n    self.fillStyle(context, 255, 255, 255, 1);\n    self.strokeStyle(context, 255, 255, 255, 1);\n\n    self.drawArrowShape( edge, prefix, context,\n      arrowClearFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,\n      x, y, angle\n    );\n\n    context.globalCompositeOperation = gco;\n  } // otherwise, the opaque arrow clears it for free :)\n\n  var color = style[prefix + '-arrow-color'].value;\n  self.fillStyle(context, color[0], color[1], color[2], style.opacity.value);\n  self.strokeStyle(context, color[0], color[1], color[2], style.opacity.value);\n\n  self.drawArrowShape( edge, prefix, context,\n    arrowFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,\n    x, y, angle\n  );\n};\n\nCRp.drawArrowShape = function(edge, arrowType, context, fill, edgeWidth, shape, x, y, angle) {\n  var r = this;\n  var usePaths = this.usePaths();\n  var rs = edge._private.rscratch;\n  var pathCacheHit = false;\n  var path;\n  var canvasContext = context;\n  var translation = { x: x, y: y };\n  var size = this.getArrowWidth( edgeWidth );\n  var shapeImpl = r.arrowShapes[shape];\n\n  if( usePaths ){\n    var pathCacheKey = size + '$' + shape + '$' + angle + '$' + x + '$' + y;\n    rs.arrowPathCacheKey = rs.arrowPathCacheKey || {};\n    rs.arrowPathCache = rs.arrowPathCache || {};\n\n    var alreadyCached = rs.arrowPathCacheKey[arrowType] === pathCacheKey;\n    if( alreadyCached ){\n      path = context = rs.arrowPathCache[arrowType];\n      pathCacheHit = true;\n    } else {\n      path = context = new Path2D();\n      rs.arrowPathCacheKey[arrowType] = pathCacheKey;\n      rs.arrowPathCache[arrowType] = path;\n    }\n  }\n\n  if( context.beginPath ){ context.beginPath(); }\n\n  if( !pathCacheHit ){\n    shapeImpl.draw(context, size, angle, translation);\n  }\n\n  if( !shapeImpl.leavePathOpen && context.closePath ){\n    context.closePath();\n  }\n\n  context = canvasContext;\n\n  if( fill === 'filled' || fill === 'both' ){\n    if( usePaths ){\n      context.fill( path );\n    } else {\n      context.fill();\n    }\n  }\n\n  if( fill === 'hollow' || fill === 'both' ){\n    context.lineWidth = ( shapeImpl.matchEdgeWidth ? edgeWidth : 1 );\n    context.lineJoin = 'miter';\n\n    if( usePaths ){\n      context.stroke( path );\n    } else {\n      context.stroke();\n    }\n\n  }\n};\n\nmodule.exports = CRp;\n\n},{}],64:[function(_dereq_,module,exports){\n'use strict';\n\nvar CRp = {};\n\nCRp.safeDrawImage = function( context, img, ix, iy, iw, ih, x, y, w, h ){\n  var r = this;\n\n  try {\n    context.drawImage( img, ix, iy, iw, ih, x, y, w, h );\n  } catch(e){\n    r.data.canvasNeedsRedraw[r.NODE] = true;\n    r.data.canvasNeedsRedraw[r.DRAG] = true;\n\n    r.drawingImage = true;\n\n    r.redraw();\n  }\n};\n\nCRp.drawInscribedImage = function(context, img, node) {\n  var r = this;\n  var nodeX = node._private.position.x;\n  var nodeY = node._private.position.y;\n  var style = node._private.style;\n  var fit = style['background-fit'].value;\n  var xPos = style['background-position-x'];\n  var yPos = style['background-position-y'];\n  var repeat = style['background-repeat'].value;\n  var nodeW = node.width();\n  var nodeH = node.height();\n  var rs = node._private.rscratch;\n  var clip = style['background-clip'].value;\n  var shouldClip = clip === 'node';\n  var imgOpacity = style['background-image-opacity'].value;\n\n  var imgW = img.width || img.cachedW;\n  var imgH = img.height || img.cachedH;\n\n  // workaround for broken browsers like ie\n  if( null == imgW || null == imgH ){\n    document.body.appendChild( img );\n\n    imgW = img.cachedW = img.width || img.offsetWidth;\n    imgH = img.cachedH = img.height || img.offsetHeight;\n\n    document.body.removeChild( img );\n  }\n\n  var w = imgW;\n  var h = imgH;\n\n  var bgW = style['background-width'];\n  if( bgW.value !== 'auto' ){\n    if( bgW.units === '%' ){\n      w = bgW.value/100 * nodeW;\n    } else {\n      w = bgW.pfValue;\n    }\n  }\n\n  var bgH = style['background-height'];\n  if( bgH.value !== 'auto' ){\n    if( bgH.units === '%' ){\n      h = bgH.value/100 * nodeH;\n    } else {\n      h = bgH.pfValue;\n    }\n  }\n\n  if( w === 0 || h === 0 ){\n    return; // no point in drawing empty image (and chrome is broken in this case)\n  }\n\n  if( fit === 'contain' ){\n    var scale = Math.min( nodeW/w, nodeH/h );\n\n    w *= scale;\n    h *= scale;\n\n  } else if( fit === 'cover' ){\n    var scale = Math.max( nodeW/w, nodeH/h );\n\n    w *= scale;\n    h *= scale;\n  }\n\n  var x = (nodeX - nodeW/2); // left\n  if( xPos.units === '%' ){\n    x += (nodeW - w) * xPos.value/100;\n  } else {\n    x += xPos.pfValue;\n  }\n\n  var y = (nodeY - nodeH/2); // top\n  if( yPos.units === '%' ){\n    y += (nodeH - h) * yPos.value/100;\n  } else {\n    y += yPos.pfValue;\n  }\n\n  if( rs.pathCache ){\n    x -= nodeX;\n    y -= nodeY;\n\n    nodeX = 0;\n    nodeY = 0;\n  }\n\n  var gAlpha = context.globalAlpha;\n\n  context.globalAlpha = imgOpacity;\n\n  if( repeat === 'no-repeat' ){\n\n    if( shouldClip ){\n      context.save();\n\n      if( rs.pathCache ){\n        context.clip( rs.pathCache );\n      } else {\n        r.nodeShapes[r.getNodeShape(node)].draw(\n          context,\n          nodeX, nodeY,\n          nodeW, nodeH);\n\n        context.clip();\n      }\n    }\n\n    r.safeDrawImage( context, img, 0, 0, imgW, imgH, x, y, w, h );\n\n    if( shouldClip ){\n      context.restore();\n    }\n  } else {\n    var pattern = context.createPattern( img, repeat );\n    context.fillStyle = pattern;\n\n    r.nodeShapes[r.getNodeShape(node)].draw(\n        context,\n        nodeX, nodeY,\n        nodeW, nodeH);\n\n      context.translate(x, y);\n      context.fill();\n      context.translate(-x, -y);\n  }\n\n  context.globalAlpha = gAlpha;\n\n};\n\nmodule.exports = CRp;\n\n},{}],65:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../../is');\n\nvar CRp = {};\n\n// Draw edge text\nCRp.drawEdgeText = function(context, edge) {\n  var text = edge._private.style['label'].strValue;\n\n  if( !text || text.match(/^\\s+$/) ){\n    return;\n  }\n\n  if( this.hideEdgesOnViewport && (this.dragData.didDrag || this.pinching || this.hoverData.dragging || this.data.wheel || this.swipePanning) ){ return; } // save cycles on pinching\n\n  var computedSize = edge._private.style['font-size'].pfValue * edge.cy().zoom();\n  var minSize = edge._private.style['min-zoomed-font-size'].pfValue;\n\n  if( computedSize < minSize ){\n    return;\n  }\n\n  // Calculate text draw position\n\n  context.textAlign = 'center';\n  context.textBaseline = 'middle';\n\n  var rs = edge._private.rscratch;\n  if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered\n\n  var style = edge._private.style;\n  var autorotate = style['edge-text-rotation'].strValue === 'autorotate';\n  var theta;\n\n  if( autorotate ){\n    theta = rs.labelAngle;\n\n    context.translate(rs.labelX, rs.labelY);\n    context.rotate(theta);\n\n    this.drawText(context, edge, 0, 0);\n\n    context.rotate(-theta);\n    context.translate(-rs.labelX, -rs.labelY);\n  } else {\n    this.drawText(context, edge, rs.labelX, rs.labelY);\n  }\n\n};\n\n// Draw node text\nCRp.drawNodeText = function(context, node) {\n  var text = node._private.style['label'].strValue;\n\n  if ( !text || text.match(/^\\s+$/) ) {\n    return;\n  }\n\n  var computedSize = node._private.style['font-size'].pfValue * node.cy().zoom();\n  var minSize = node._private.style['min-zoomed-font-size'].pfValue;\n\n  if( computedSize < minSize ){\n    return;\n  }\n\n  // this.recalculateNodeLabelProjection( node );\n\n  var textHalign = node._private.style['text-halign'].strValue;\n  var textValign = node._private.style['text-valign'].strValue;\n  var rs = node._private.rscratch;\n  if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered\n\n  switch( textHalign ){\n    case 'left':\n      context.textAlign = 'right';\n      break;\n\n    case 'right':\n      context.textAlign = 'left';\n      break;\n\n    default: // e.g. center\n      context.textAlign = 'center';\n  }\n\n  switch( textValign ){\n    case 'top':\n      context.textBaseline = 'bottom';\n      break;\n\n    case 'bottom':\n      context.textBaseline = 'top';\n      break;\n\n    default: // e.g. center\n      context.textBaseline = 'middle';\n  }\n\n  this.drawText(context, node, rs.labelX, rs.labelY);\n};\n\nCRp.getFontCache = function(context){\n  var cache;\n\n  this.fontCaches = this.fontCaches || [];\n\n  for( var i = 0; i < this.fontCaches.length; i++ ){\n    cache = this.fontCaches[i];\n\n    if( cache.context === context ){\n      return cache;\n    }\n  }\n\n  cache = {\n    context: context\n  };\n  this.fontCaches.push(cache);\n\n  return cache;\n};\n\n// set up canvas context with font\n// returns transformed text string\nCRp.setupTextStyle = function( context, element ){\n  // Font style\n  var parentOpacity = element.effectiveOpacity();\n  var style = element._private.style;\n  var labelStyle = style['font-style'].strValue;\n  var labelSize = style['font-size'].pfValue + 'px';\n  var labelFamily = style['font-family'].strValue;\n  var labelWeight = style['font-weight'].strValue;\n  var opacity = style['text-opacity'].value * style['opacity'].value * parentOpacity;\n  var outlineOpacity = style['text-outline-opacity'].value * opacity;\n  var color = style['color'].value;\n  var outlineColor = style['text-outline-color'].value;\n  var shadowBlur = style['text-shadow-blur'].pfValue;\n  var shadowOpacity = style['text-shadow-opacity'].value;\n  var shadowColor = style['text-shadow-color'].value;\n  var shadowOffsetX = style['text-shadow-offset-x'].pfValue;\n  var shadowOffsetY = style['text-shadow-offset-y'].pfValue;\n\n  var fontCacheKey = element._private.fontKey;\n  var cache = this.getFontCache(context);\n\n  if( cache.key !== fontCacheKey ){\n    context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily;\n\n    cache.key = fontCacheKey;\n  }\n\n  var text = this.getLabelText( element );\n\n  // Calculate text draw position based on text alignment\n\n  // so text outlines aren't jagged\n  context.lineJoin = 'round';\n\n  this.fillStyle(context, color[0], color[1], color[2], opacity);\n\n  this.strokeStyle(context, outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity);\n\n  this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n  return text;\n};\n\nfunction roundRect(ctx, x, y, width, height, radius) {\n  var radius = radius || 5;\n  ctx.beginPath();\n  ctx.moveTo(x + radius, y);\n  ctx.lineTo(x + width - radius, y);\n  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n  ctx.lineTo(x + width, y + height - radius);\n  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n  ctx.lineTo(x + radius, y + height);\n  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n  ctx.lineTo(x, y + radius);\n  ctx.quadraticCurveTo(x, y, x + radius, y);\n  ctx.closePath();\n  ctx.fill();\n}\n\n// Draw text\nCRp.drawText = function(context, element, textX, textY) {\n  var _p = element._private;\n  var style = _p.style;\n  var rstyle = _p.rstyle;\n  var rscratch = _p.rscratch;\n  var parentOpacity = element.effectiveOpacity();\n  if( parentOpacity === 0 || style['text-opacity'].value === 0){ return; }\n\n  var text = this.setupTextStyle( context, element );\n  var halign = style['text-halign'].value;\n  var valign = style['text-valign'].value;\n\n  if( element.isEdge() ){\n    halign = 'center';\n    valign = 'center';\n  }\n\n  if( element.isNode() ){\n    var pLeft = style['padding-left'].pfValue;\n    var pRight = style['padding-right'].pfValue;\n    var pTop = style['padding-top'].pfValue;\n    var pBottom = style['padding-bottom'].pfValue;\n\n    textX += pLeft/2;\n    textX -= pRight/2;\n\n    textY += pTop/2;\n    textY -= pBottom/2;\n  }\n\n  if ( text != null && !isNaN(textX) && !isNaN(textY)) {\n    var backgroundOpacity = style['text-background-opacity'].value;\n    var borderOpacity = style['text-border-opacity'].value;\n    var textBorderWidth = style['text-border-width'].pfValue;\n\n    if( backgroundOpacity > 0 || (textBorderWidth > 0 && borderOpacity > 0) ){\n      var margin = 4 + textBorderWidth/2;\n\n      if (element.isNode()) {\n        //Move textX, textY to include the background margins\n        if (valign === 'top') {\n          textY -= margin;\n        } else if (valign === 'bottom') {\n          textY += margin;\n        }\n        if (halign === 'left') {\n          textX -= margin;\n        } else if (halign === 'right') {\n          textX += margin;\n        }\n      }\n\n      var bgWidth = rstyle.labelWidth;\n      var bgHeight = rstyle.labelHeight;\n      var bgX = textX;\n\n      if (halign) {\n        if (halign == 'center') {\n          bgX = bgX - bgWidth / 2;\n        } else if (halign == 'left') {\n          bgX = bgX- bgWidth;\n        }\n      }\n\n      var bgY = textY;\n\n      if (element.isNode()) {\n        if (valign == 'top') {\n           bgY = bgY - bgHeight;\n        } else if (valign == 'center') {\n          bgY = bgY- bgHeight / 2;\n        }\n      } else {\n        bgY = bgY - bgHeight / 2;\n      }\n\n      if (style['edge-text-rotation'].strValue === 'autorotate') {\n        textY = 0;\n        bgWidth += 4;\n        bgX = textX - bgWidth / 2;\n        bgY = textY - bgHeight / 2;\n      } else {\n        // Adjust with border width & margin\n        bgX -= margin;\n        bgY -= margin;\n        bgHeight += margin*2;\n        bgWidth += margin*2;\n      }\n\n      if( backgroundOpacity > 0 ){\n        var textFill = context.fillStyle;\n        var textBackgroundColor = style['text-background-color'].value;\n\n        context.fillStyle = 'rgba(' + textBackgroundColor[0] + ',' + textBackgroundColor[1] + ',' + textBackgroundColor[2] + ',' + backgroundOpacity * parentOpacity + ')';\n        var styleShape = style['text-background-shape'].strValue;\n        if (styleShape == 'roundrectangle') {\n          roundRect(context, bgX, bgY, bgWidth, bgHeight, 2);\n        } else {\n          context.fillRect(bgX,bgY,bgWidth,bgHeight);\n        }\n        context.fillStyle = textFill;\n      }\n\n      if( textBorderWidth > 0 && borderOpacity > 0 ){\n        var textStroke = context.strokeStyle;\n        var textLineWidth = context.lineWidth;\n        var textBorderColor = style['text-border-color'].value;\n        var textBorderStyle = style['text-border-style'].value;\n\n        context.strokeStyle = 'rgba(' + textBorderColor[0] + ',' + textBorderColor[1] + ',' + textBorderColor[2] + ',' + borderOpacity * parentOpacity + ')';\n        context.lineWidth = textBorderWidth;\n\n        if( context.setLineDash ){ // for very outofdate browsers\n          switch( textBorderStyle ){\n            case 'dotted':\n              context.setLineDash([ 1, 1 ]);\n              break;\n            case 'dashed':\n              context.setLineDash([ 4, 2 ]);\n              break;\n            case 'double':\n              context.lineWidth = textBorderWidth/4; // 50% reserved for white between the two borders\n              context.setLineDash([ ]);\n              break;\n            case 'solid':\n              context.setLineDash([ ]);\n              break;\n          }\n        }\n\n        context.strokeRect(bgX,bgY,bgWidth,bgHeight);\n\n        if( textBorderStyle === 'double' ){\n          var whiteWidth = textBorderWidth/2;\n\n          context.strokeRect(bgX+whiteWidth,bgY+whiteWidth,bgWidth-whiteWidth*2,bgHeight-whiteWidth*2);\n        }\n\n        if( context.setLineDash ){ // for very outofdate browsers\n          context.setLineDash([ ]);\n        }\n        context.lineWidth = textLineWidth;\n        context.strokeStyle = textStroke;\n      }\n\n    }\n\n    var lineWidth = 2  * style['text-outline-width'].pfValue; // *2 b/c the stroke is drawn centred on the middle\n\n    if( lineWidth > 0 ){\n      context.lineWidth = lineWidth;\n    }\n\n    if( style['text-wrap'].value === 'wrap' ){\n      var lines = rscratch.labelWrapCachedLines;\n      var lineHeight = rstyle.labelHeight / lines.length;\n\n      switch( valign ){\n        case 'top':\n          textY -= (lines.length - 1) * lineHeight;\n          break;\n\n        case 'bottom':\n          // nothing required\n          break;\n\n        default:\n        case 'center':\n          textY -= (lines.length - 1) * lineHeight / 2;\n      }\n\n      for( var l = 0; l < lines.length; l++ ){\n        if( lineWidth > 0 ){\n          context.strokeText( lines[l], textX, textY );\n        }\n\n        context.fillText( lines[l], textX, textY );\n\n        textY += lineHeight;\n      }\n\n    } else {\n      if( lineWidth > 0 ){\n        context.strokeText( text, textX, textY );\n      }\n\n      context.fillText( text, textX, textY );\n    }\n\n\n    this.shadowStyle(context, 'transparent', 0); // reset for next guy\n  }\n};\n\n\nmodule.exports = CRp;\n\n},{\"../../../is\":77}],66:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../../is');\n\nvar CRp = {};\n\n// Draw node\nCRp.drawNode = function(context, node, drawOverlayInstead) {\n\n  var r = this;\n  var nodeWidth, nodeHeight;\n  var style = node._private.style;\n  var rs = node._private.rscratch;\n  var _p = node._private;\n  var pos = _p.position;\n\n  if( !is.number(pos.x) || !is.number(pos.y) ){\n    return; // can't draw node with undefined position\n  }\n\n  var usePaths = this.usePaths();\n  var canvasContext = context;\n  var path;\n  var pathCacheHit = false;\n\n  var overlayPadding = style['overlay-padding'].pfValue;\n  var overlayOpacity = style['overlay-opacity'].value;\n  var overlayColor = style['overlay-color'].value;\n\n  if( drawOverlayInstead && overlayOpacity === 0 ){ // exit early if drawing overlay but none to draw\n    return;\n  }\n\n  var parentOpacity = node.effectiveOpacity();\n  if( parentOpacity === 0 ){ return; }\n\n  nodeWidth = node.width() + style['padding-left'].pfValue + style['padding-right'].pfValue;\n  nodeHeight = node.height() + style['padding-top'].pfValue + style['padding-bottom'].pfValue;\n\n  context.lineWidth = style['border-width'].pfValue;\n\n  if( drawOverlayInstead === undefined || !drawOverlayInstead ){\n\n    var url = style['background-image'].value[2] ||\n      style['background-image'].value[1];\n    var image;\n\n    if (url !== undefined) {\n\n      // get image, and if not loaded then ask to redraw when later loaded\n      image = this.getCachedImage(url, function(){\n        r.data.canvasNeedsRedraw[r.NODE] = true;\n        r.data.canvasNeedsRedraw[r.DRAG] = true;\n\n        r.drawingImage = true;\n\n        r.redraw();\n      });\n\n      var prevBging = _p.backgrounding;\n      _p.backgrounding = !image.complete;\n\n      if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed\n        node.updateStyle( false );\n      }\n    }\n\n    // Node color & opacity\n\n    var bgColor = style['background-color'].value;\n    var borderColor = style['border-color'].value;\n    var borderStyle = style['border-style'].value;\n\n    this.fillStyle(context, bgColor[0], bgColor[1], bgColor[2], style['background-opacity'].value * parentOpacity);\n\n    this.strokeStyle(context, borderColor[0], borderColor[1], borderColor[2], style['border-opacity'].value * parentOpacity);\n\n    var shadowBlur = style['shadow-blur'].pfValue;\n    var shadowOpacity = style['shadow-opacity'].value;\n    var shadowColor = style['shadow-color'].value;\n    var shadowOffsetX = style['shadow-offset-x'].pfValue;\n    var shadowOffsetY = style['shadow-offset-y'].pfValue;\n\n    this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n    context.lineJoin = 'miter'; // so borders are square with the node shape\n\n    if( context.setLineDash ){ // for very outofdate browsers\n      switch( borderStyle ){\n        case 'dotted':\n          context.setLineDash([ 1, 1 ]);\n          break;\n\n        case 'dashed':\n          context.setLineDash([ 4, 2 ]);\n          break;\n\n        case 'solid':\n        case 'double':\n          context.setLineDash([ ]);\n          break;\n      }\n    }\n\n\n    var styleShape = style['shape'].strValue;\n\n    if( usePaths ){\n      var pathCacheKey = styleShape + '$' + nodeWidth +'$' + nodeHeight;\n\n      context.translate( pos.x, pos.y );\n\n      if( rs.pathCacheKey === pathCacheKey ){\n        path = context = rs.pathCache;\n        pathCacheHit = true;\n      } else {\n        path = context = new Path2D();\n        rs.pathCacheKey = pathCacheKey;\n        rs.pathCache = path;\n      }\n    }\n\n    if( !pathCacheHit ){\n\n      var npos = pos;\n\n      if( usePaths ){\n        npos = {\n          x: 0,\n          y: 0\n        };\n      }\n\n      r.nodeShapes[this.getNodeShape(node)].draw(\n            context,\n            npos.x,\n            npos.y,\n            nodeWidth,\n            nodeHeight);\n    }\n\n    context = canvasContext;\n\n    if( usePaths ){\n      context.fill( path );\n    } else {\n      context.fill();\n    }\n\n    this.shadowStyle(context, 'transparent', 0); // reset for next guy\n\n    if (url !== undefined) {\n      if( image.complete ){\n        this.drawInscribedImage(context, image, node);\n      }\n    }\n\n    var darkness = style['background-blacken'].value;\n    var borderWidth = style['border-width'].pfValue;\n\n    if( this.hasPie(node) ){\n      this.drawPie( context, node, parentOpacity );\n\n      // redraw path for blacken and border\n      if( darkness !== 0 || borderWidth !== 0 ){\n\n        if( !usePaths ){\n          r.nodeShapes[this.getNodeShape(node)].draw(\n              context,\n              pos.x,\n              pos.y,\n              nodeWidth,\n              nodeHeight);\n        }\n      }\n    }\n\n    if( darkness > 0 ){\n      this.fillStyle(context, 0, 0, 0, darkness);\n\n      if( usePaths ){\n        context.fill( path );\n      } else {\n        context.fill();\n      }\n\n    } else if( darkness < 0 ){\n      this.fillStyle(context, 255, 255, 255, -darkness);\n\n      if( usePaths ){\n        context.fill( path );\n      } else {\n        context.fill();\n      }\n    }\n\n    // Border width, draw border\n    if (borderWidth > 0) {\n\n      if( usePaths ){\n        context.stroke( path );\n      } else {\n        context.stroke();\n      }\n\n      if( borderStyle === 'double' ){\n        context.lineWidth = style['border-width'].pfValue/3;\n\n        var gco = context.globalCompositeOperation;\n        context.globalCompositeOperation = 'destination-out';\n\n        if( usePaths ){\n          context.stroke( path );\n        } else {\n          context.stroke();\n        }\n\n        context.globalCompositeOperation = gco;\n      }\n\n    }\n\n    if( usePaths ){\n      context.translate( -pos.x, -pos.y );\n    }\n\n    // reset in case we changed the border style\n    if( context.setLineDash ){ // for very outofdate browsers\n      context.setLineDash([ ]);\n    }\n\n  // draw the overlay\n  } else {\n\n    if( overlayOpacity > 0 ){\n      this.fillStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n\n      r.nodeShapes['roundrectangle'].draw(\n        context,\n        node._private.position.x,\n        node._private.position.y,\n        nodeWidth + overlayPadding * 2,\n        nodeHeight + overlayPadding * 2\n      );\n\n      context.fill();\n    }\n  }\n\n};\n\n// does the node have at least one pie piece?\nCRp.hasPie = function(node){\n  node = node[0]; // ensure ele ref\n\n  return node._private.hasPie;\n};\n\nCRp.drawPie = function( context, node, nodeOpacity ){\n  node = node[0]; // ensure ele ref\n\n  var _p = node._private;\n  var cyStyle = node.cy().style();\n  var style = _p.style;\n  var pieSize = style['pie-size'];\n  var nodeW = node.width();\n  var nodeH = node.height();\n  var x = _p.position.x;\n  var y = _p.position.y;\n  var radius = Math.min( nodeW, nodeH ) / 2; // must fit in node\n  var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]\n  var usePaths = this.usePaths();\n\n  if( usePaths ){\n    x = 0;\n    y = 0;\n  }\n\n  if( pieSize.units === '%' ){\n    radius = radius * pieSize.value / 100;\n  } else if( pieSize.pfValue !== undefined ){\n    radius = pieSize.pfValue / 2;\n  }\n\n  for( var i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N\n    var size = style['pie-' + i + '-background-size'].value;\n    var color = style['pie-' + i + '-background-color'].value;\n    var opacity = style['pie-' + i + '-background-opacity'].value * nodeOpacity;\n    var percent = size / 100; // map integer range [0, 100] to [0, 1]\n\n    // percent can't push beyond 1\n    if( percent + lastPercent > 1 ){\n      percent = 1 - lastPercent;\n    }\n\n    var angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise\n    var angleDelta = 2 * Math.PI * percent;\n    var angleEnd = angleStart + angleDelta;\n\n    // ignore if\n    // - zero size\n    // - we're already beyond the full circle\n    // - adding the current slice would go beyond the full circle\n    if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){\n      continue;\n    }\n\n    context.beginPath();\n    context.moveTo(x, y);\n    context.arc( x, y, radius, angleStart, angleEnd );\n    context.closePath();\n\n    this.fillStyle(context, color[0], color[1], color[2], opacity);\n\n    context.fill();\n\n    lastPercent += percent;\n  }\n\n};\n\n\nmodule.exports = CRp;\n\n},{\"../../../is\":77}],67:[function(_dereq_,module,exports){\n'use strict';\n\nvar CRp = {};\n\nvar util = _dereq_('../../../util');\nvar math = _dereq_('../../../math');\n\nvar motionBlurDelay = 100;\n\n// var isFirefox = typeof InstallTrigger !== 'undefined';\n\nCRp.getPixelRatio = function(){\n  var context = this.data.contexts[0];\n\n  if( this.forcedPixelRatio != null ){\n    return this.forcedPixelRatio;\n  }\n\n  var backingStore = context.backingStorePixelRatio ||\n    context.webkitBackingStorePixelRatio ||\n    context.mozBackingStorePixelRatio ||\n    context.msBackingStorePixelRatio ||\n    context.oBackingStorePixelRatio ||\n    context.backingStorePixelRatio || 1;\n\n  return (window.devicePixelRatio || 1) / backingStore;\n};\n\nCRp.paintCache = function(context){\n  var caches = this.paintCaches = this.paintCaches || [];\n  var needToCreateCache = true;\n  var cache;\n\n  for(var i = 0; i < caches.length; i++ ){\n    cache = caches[i];\n\n    if( cache.context === context ){\n      needToCreateCache = false;\n      break;\n    }\n  }\n\n  if( needToCreateCache ){\n    cache = {\n      context: context\n    };\n    caches.push( cache );\n  }\n\n  return cache;\n};\n\nCRp.fillStyle = function(context, r, g, b, a){\n  context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // turn off for now, seems context does its own caching\n\n  // var cache = this.paintCache(context);\n\n  // var fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // if( cache.fillStyle !== fillStyle ){\n  //   context.fillStyle = cache.fillStyle = fillStyle;\n  // }\n};\n\nCRp.strokeStyle = function(context, r, g, b, a){\n  context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // turn off for now, seems context does its own caching\n\n  // var cache = this.paintCache(context);\n\n  // var strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // if( cache.strokeStyle !== strokeStyle ){\n  //   context.strokeStyle = cache.strokeStyle = strokeStyle;\n  // }\n};\n\nCRp.shadowStyle = function(context, color, opacity, blur, offsetX, offsetY){\n  var zoom = this.cy.zoom();\n\n  var cache = this.paintCache(context);\n\n  // don't make expensive changes to the shadow style if it's not used\n  if( cache.shadowOpacity === 0 && opacity === 0 ){\n    return;\n  }\n\n  cache.shadowOpacity = opacity;\n\n  if (opacity > 0) {\n    context.shadowBlur = blur * zoom;\n    context.shadowColor = \"rgba(\" + color[0] + \",\" + color[1] + \",\" + color[2] + \",\" + opacity + \")\";\n    context.shadowOffsetX = offsetX * zoom;\n    context.shadowOffsetY = offsetY * zoom;\n  } else {\n    context.shadowBlur = 0;\n    context.shadowColor = \"transparent\";\n  }\n};\n\n// Resize canvas\nCRp.matchCanvasSize = function(container) {\n  var r = this;\n  var data = r.data;\n  var width = container.clientWidth;\n  var height = container.clientHeight;\n  var pixelRatio = r.getPixelRatio();\n  var mbPxRatio = r.motionBlurPxRatio;\n\n  if(\n    container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE] ||\n    container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]\n  ){\n    pixelRatio = mbPxRatio;\n  }\n\n  var canvasWidth = width * pixelRatio;\n  var canvasHeight = height * pixelRatio;\n  var canvas;\n\n  if( canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight ){\n    return; // save cycles if same\n  }\n\n  r.fontCaches = null; // resizing resets the style\n\n  var canvasContainer = data.canvasContainer;\n  canvasContainer.style.width = width + 'px';\n  canvasContainer.style.height = height + 'px';\n\n  for (var i = 0; i < r.CANVAS_LAYERS; i++) {\n\n    canvas = data.canvases[i];\n\n    if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\n      canvas.width = canvasWidth;\n      canvas.height = canvasHeight;\n\n      canvas.style.width = width + 'px';\n      canvas.style.height = height + 'px';\n    }\n  }\n\n  for (var i = 0; i < r.BUFFER_COUNT; i++) {\n\n    canvas = data.bufferCanvases[i];\n\n    if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\n      canvas.width = canvasWidth;\n      canvas.height = canvasHeight;\n\n      canvas.style.width = width + 'px';\n      canvas.style.height = height + 'px';\n    }\n  }\n\n  r.textureMult = 1;\n  if( pixelRatio <= 1 ){\n    canvas = data.bufferCanvases[ r.TEXTURE_BUFFER ];\n\n    r.textureMult = 2;\n    canvas.width = canvasWidth * r.textureMult;\n    canvas.height = canvasHeight * r.textureMult;\n  }\n\n  r.canvasWidth = canvasWidth;\n  r.canvasHeight = canvasHeight;\n\n};\n\nCRp.renderTo = function( cxt, zoom, pan, pxRatio ){\n  this.render({\n    forcedContext: cxt,\n    forcedZoom: zoom,\n    forcedPan: pan,\n    drawAllLayers: true,\n    forcedPxRatio: pxRatio\n  });\n};\n\nCRp.render = function( options ) {\n  options = options || util.staticEmptyObject();\n\n  var forcedContext = options.forcedContext;\n  var drawAllLayers = options.drawAllLayers;\n  var drawOnlyNodeLayer = options.drawOnlyNodeLayer;\n  var forcedZoom = options.forcedZoom;\n  var forcedPan = options.forcedPan;\n  var r = this;\n  var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio;\n  var cy = r.cy; var data = r.data;\n  var needDraw = data.canvasNeedsRedraw;\n  var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming);\n  var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur;\n  var mbPxRatio = r.motionBlurPxRatio;\n  var hasCompoundNodes = cy.hasCompoundNodes();\n  var inNodeDragGesture = r.hoverData.draggingEles;\n  var inBoxSelection = r.hoverData.selecting || r.touchData.selecting ? true : false;\n  motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection;\n  var motionBlurFadeEffect = motionBlur;\n\n  if( !forcedContext && r.motionBlurTimeout ){\n    clearTimeout( r.motionBlurTimeout );\n  }\n\n  if( motionBlur ){\n    if( r.mbFrames == null ){\n      r.mbFrames = 0;\n    }\n\n    if( !r.drawingImage ){ // image loading frames don't count towards motion blur blurry frames\n      r.mbFrames++;\n    }\n\n    if( r.mbFrames < 3 ){ // need several frames before even high quality motionblur\n      motionBlurFadeEffect = false;\n    }\n\n    // go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing)\n    if( r.mbFrames > r.minMbLowQualFrames ){\n      //r.fullQualityMb = false;\n      r.motionBlurPxRatio = r.mbPxRBlurry;\n    }\n  }\n\n  if( r.clearingMotionBlur ){\n    r.motionBlurPxRatio = 1;\n  }\n\n  // b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame\n  // because a rogue async texture frame would clear needDraw\n  if( r.textureDrawLastFrame && !textureDraw ){\n    needDraw[r.NODE] = true;\n    needDraw[r.SELECT_BOX] = true;\n  }\n\n  var edges = r.getCachedEdges();\n  var coreStyle = cy.style()._private.coreStyle;\n\n  var zoom = cy.zoom();\n  var effectiveZoom = forcedZoom !== undefined ? forcedZoom : zoom;\n  var pan = cy.pan();\n  var effectivePan = {\n    x: pan.x,\n    y: pan.y\n  };\n\n  var vp = {\n    zoom: zoom,\n    pan: {\n      x: pan.x,\n      y: pan.y\n    }\n  };\n  var prevVp = r.prevViewport;\n  var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y;\n\n  // we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed)\n  if( !viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes) ){\n    r.motionBlurPxRatio = 1;\n  }\n\n  if( forcedPan ){\n    effectivePan = forcedPan;\n  }\n\n  // apply pixel ratio\n\n  effectiveZoom *= pixelRatio;\n  effectivePan.x *= pixelRatio;\n  effectivePan.y *= pixelRatio;\n\n  var eles = {\n    drag: {\n      nodes: [],\n      edges: [],\n      eles: []\n    },\n    nondrag: {\n      nodes: [],\n      edges: [],\n      eles: []\n    }\n  };\n\n  function mbclear( context, x, y, w, h ){\n    var gco = context.globalCompositeOperation;\n\n    context.globalCompositeOperation = 'destination-out';\n    r.fillStyle( context, 255, 255, 255, r.motionBlurTransparency );\n    context.fillRect(x, y, w, h);\n\n    context.globalCompositeOperation = gco;\n  }\n\n  function setContextTransform(context, clear){\n    var ePan, eZoom, w, h;\n\n    if( !r.clearingMotionBlur && (context === data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] || context === data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG]) ){\n      ePan = {\n        x: pan.x * mbPxRatio,\n        y: pan.y * mbPxRatio\n      };\n\n      eZoom = zoom * mbPxRatio;\n\n      w = r.canvasWidth * mbPxRatio;\n      h = r.canvasHeight * mbPxRatio;\n    } else {\n      ePan = effectivePan;\n      eZoom = effectiveZoom;\n\n      w = r.canvasWidth;\n      h = r.canvasHeight;\n    }\n\n    context.setTransform(1, 0, 0, 1, 0, 0);\n\n    if( clear === 'motionBlur' ){\n      mbclear(context, 0, 0, w, h);\n    } else if( !forcedContext && (clear === undefined || clear) ){\n      context.clearRect(0, 0, w, h);\n    }\n\n    if( !drawAllLayers ){\n      context.translate( ePan.x, ePan.y );\n      context.scale( eZoom, eZoom );\n    }\n    if( forcedPan ){\n      context.translate( forcedPan.x, forcedPan.y );\n    }\n    if( forcedZoom ){\n      context.scale( forcedZoom, forcedZoom );\n    }\n  }\n\n  if( !textureDraw ){\n    r.textureDrawLastFrame = false;\n  }\n\n  if( textureDraw ){\n    r.textureDrawLastFrame = true;\n\n    var bb;\n\n    if( !r.textureCache ){\n      r.textureCache = {};\n\n      bb = r.textureCache.bb = cy.elements().boundingBox();\n\n      r.textureCache.texture = r.data.bufferCanvases[ r.TEXTURE_BUFFER ];\n\n      var cxt = r.data.bufferContexts[ r.TEXTURE_BUFFER ];\n\n      cxt.setTransform(1, 0, 0, 1, 0, 0);\n      cxt.clearRect(0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult);\n\n      r.render({\n        forcedContext: cxt,\n        drawOnlyNodeLayer: true,\n        forcedPxRatio: pixelRatio * r.textureMult\n      });\n\n      var vp = r.textureCache.viewport = {\n        zoom: cy.zoom(),\n        pan: cy.pan(),\n        width: r.canvasWidth,\n        height: r.canvasHeight\n      };\n\n      vp.mpan = {\n        x: (0 - vp.pan.x)/vp.zoom,\n        y: (0 - vp.pan.y)/vp.zoom\n      };\n    }\n\n    needDraw[r.DRAG] = false;\n    needDraw[r.NODE] = false;\n\n    var context = data.contexts[r.NODE];\n\n    var texture = r.textureCache.texture;\n    var vp = r.textureCache.viewport;\n    bb = r.textureCache.bb;\n\n    context.setTransform(1, 0, 0, 1, 0, 0);\n\n    if( motionBlur ){\n      mbclear(context, 0, 0, vp.width, vp.height);\n    } else {\n      context.clearRect(0, 0, vp.width, vp.height);\n    }\n\n    var outsideBgColor = coreStyle['outside-texture-bg-color'].value;\n    var outsideBgOpacity = coreStyle['outside-texture-bg-opacity'].value;\n    r.fillStyle( context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity );\n    context.fillRect( 0, 0, vp.width, vp.height );\n\n    var zoom = cy.zoom();\n\n    setContextTransform( context, false );\n\n    context.clearRect( vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );\n    context.drawImage( texture, vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );\n\n  } else if( r.textureOnViewport && !forcedContext ){ // clear the cache since we don't need it\n    r.textureCache = null;\n  }\n\n  var vpManip = (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles);\n  var hideEdges = r.hideEdgesOnViewport && vpManip;\n  var hideLabels = r.hideLabelsOnViewport && vpManip;\n\n  if (needDraw[r.DRAG] || needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer) {\n    if( hideEdges ){\n    } else {\n      r.findEdgeControlPoints(edges);\n    }\n\n    var zEles = r.getCachedZSortedEles();\n    var extent = cy.extent();\n\n    for (var i = 0; i < zEles.length; i++) {\n      var ele = zEles[i];\n      var list;\n      var bb = forcedContext ? null : ele.boundingBox();\n      var insideExtent = forcedContext ? true : math.boundingBoxesIntersect( extent, bb );\n\n      if( !insideExtent ){ continue; } // no need to render\n\n      if ( ele._private.rscratch.inDragLayer ) {\n        list = eles.drag;\n      } else {\n        list = eles.nondrag;\n      }\n\n      list.eles.push( ele );\n    }\n\n  }\n\n\n  function drawElements( list, context ){\n    var eles = list.eles;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n\n      if( ele.isNode() ){\n        r.drawNode(context, ele);\n\n        if( !hideLabels ){\n          r.drawNodeText(context, ele);\n        }\n\n        r.drawNode(context, ele, true);\n      } else if( !hideEdges ) {\n        r.drawEdge(context, ele);\n\n        if( !hideLabels ){\n          r.drawEdgeText(context, ele);\n        }\n\n        r.drawEdge(context, ele, true);\n      }\n\n\n    }\n\n  }\n\n  var needMbClear = [];\n\n  needMbClear[r.NODE] = !needDraw[r.NODE] && motionBlur && !r.clearedForMotionBlur[r.NODE] || r.clearingMotionBlur;\n  if( needMbClear[r.NODE] ){ r.clearedForMotionBlur[r.NODE] = true; }\n\n  needMbClear[r.DRAG] = !needDraw[r.DRAG] && motionBlur && !r.clearedForMotionBlur[r.DRAG] || r.clearingMotionBlur;\n  if( needMbClear[r.DRAG] ){ r.clearedForMotionBlur[r.DRAG] = true; }\n\n  if( needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer || needMbClear[r.NODE] ){\n    var useBuffer = motionBlur && !needMbClear[r.NODE] && mbPxRatio !== 1;\n    var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] : data.contexts[r.NODE] );\n    var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined;\n\n    setContextTransform( context, clear );\n    drawElements(eles.nondrag, context);\n\n    if( !drawAllLayers && !motionBlur ){\n      needDraw[r.NODE] = false;\n    }\n  }\n\n  if ( !drawOnlyNodeLayer && (needDraw[r.DRAG] || drawAllLayers || needMbClear[r.DRAG]) ) {\n    var useBuffer = motionBlur && !needMbClear[r.DRAG] && mbPxRatio !== 1;\n    var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ] : data.contexts[r.DRAG] );\n\n    setContextTransform( context, motionBlur && !useBuffer ? 'motionBlur' : undefined );\n    drawElements(eles.drag, context);\n\n    if( !drawAllLayers && !motionBlur ){\n      needDraw[r.DRAG] = false;\n    }\n  }\n\n  if( r.showFps || (!drawOnlyNodeLayer && (needDraw[r.SELECT_BOX] && !drawAllLayers)) ) {\n    var context = forcedContext || data.contexts[r.SELECT_BOX];\n\n    setContextTransform( context );\n\n    if( r.selection[4] == 1 && ( r.hoverData.selecting || r.touchData.selecting ) ){\n      var zoom = r.cy.zoom();\n      var borderWidth = coreStyle['selection-box-border-width'].value / zoom;\n\n      context.lineWidth = borderWidth;\n      context.fillStyle = \"rgba(\"\n        + coreStyle['selection-box-color'].value[0] + \",\"\n        + coreStyle['selection-box-color'].value[1] + \",\"\n        + coreStyle['selection-box-color'].value[2] + \",\"\n        + coreStyle['selection-box-opacity'].value + \")\";\n\n      context.fillRect(\n        r.selection[0],\n        r.selection[1],\n        r.selection[2] - r.selection[0],\n        r.selection[3] - r.selection[1]);\n\n      if (borderWidth > 0) {\n        context.strokeStyle = \"rgba(\"\n          + coreStyle['selection-box-border-color'].value[0] + \",\"\n          + coreStyle['selection-box-border-color'].value[1] + \",\"\n          + coreStyle['selection-box-border-color'].value[2] + \",\"\n          + coreStyle['selection-box-opacity'].value + \")\";\n\n        context.strokeRect(\n          r.selection[0],\n          r.selection[1],\n          r.selection[2] - r.selection[0],\n          r.selection[3] - r.selection[1]);\n      }\n    }\n\n    if( data.bgActivePosistion && !r.hoverData.selecting ){\n      var zoom = r.cy.zoom();\n      var pos = data.bgActivePosistion;\n\n      context.fillStyle = \"rgba(\"\n        + coreStyle['active-bg-color'].value[0] + \",\"\n        + coreStyle['active-bg-color'].value[1] + \",\"\n        + coreStyle['active-bg-color'].value[2] + \",\"\n        + coreStyle['active-bg-opacity'].value + \")\";\n\n      context.beginPath();\n      context.arc(pos.x, pos.y, coreStyle['active-bg-size'].pfValue / zoom, 0, 2 * Math.PI);\n      context.fill();\n    }\n\n    var timeToRender = r.lastRedrawTime;\n    if( r.showFps && timeToRender ){\n      timeToRender = Math.round( timeToRender );\n      var fps = Math.round(1000/timeToRender);\n\n      context.setTransform(1, 0, 0, 1, 0, 0);\n\n      context.fillStyle = 'rgba(255, 0, 0, 0.75)';\n      context.strokeStyle = 'rgba(255, 0, 0, 0.75)';\n      context.lineWidth = 1;\n      context.fillText( '1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20);\n\n      var maxFps = 60;\n      context.strokeRect(0, 30, 250, 20);\n      context.fillRect(0, 30, 250 * Math.min(fps/maxFps, 1), 20);\n    }\n\n    if( !drawAllLayers ){\n      needDraw[r.SELECT_BOX] = false;\n    }\n  }\n\n  // motionblur: blit rendered blurry frames\n  if( motionBlur && mbPxRatio !== 1 ){\n    var cxtNode = data.contexts[r.NODE];\n    var txtNode = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ];\n\n    var cxtDrag = data.contexts[r.DRAG];\n    var txtDrag = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ];\n\n    var drawMotionBlur = function( cxt, txt, needClear ){\n      cxt.setTransform(1, 0, 0, 1, 0, 0);\n\n      if( needClear || !motionBlurFadeEffect ){\n        cxt.clearRect( 0, 0, r.canvasWidth, r.canvasHeight );\n      } else {\n        mbclear( cxt, 0, 0, r.canvasWidth, r.canvasHeight );\n      }\n\n      var pxr = mbPxRatio;\n\n      cxt.drawImage(\n        txt, // img\n        0, 0, // sx, sy\n        r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh\n        0, 0, // x, y\n        r.canvasWidth, r.canvasHeight // w, h\n      );\n    };\n\n    if( needDraw[r.NODE] || needMbClear[r.NODE] ){\n      drawMotionBlur( cxtNode, txtNode, needMbClear[r.NODE] );\n      needDraw[r.NODE] = false;\n    }\n\n    if( needDraw[r.DRAG] || needMbClear[r.DRAG] ){\n      drawMotionBlur( cxtDrag, txtDrag, needMbClear[r.DRAG] );\n      needDraw[r.DRAG] = false;\n    }\n  }\n\n  r.currentlyDrawing = false;\n\n  r.prevViewport = vp;\n\n  if( r.clearingMotionBlur ){\n    r.clearingMotionBlur = false;\n    r.motionBlurCleared = true;\n    r.motionBlur = true;\n  }\n\n  if( motionBlur ){\n    r.motionBlurTimeout = setTimeout(function(){\n      r.motionBlurTimeout = null;\n\n      r.clearedForMotionBlur[r.NODE] = false;\n      r.clearedForMotionBlur[r.DRAG] = false;\n      r.motionBlur = false;\n      r.clearingMotionBlur = !textureDraw;\n      r.mbFrames = 0;\n\n      needDraw[r.NODE] = true;\n      needDraw[r.DRAG] = true;\n\n      r.redraw();\n    }, motionBlurDelay);\n  }\n\n  r.drawingImage = false;\n\n\n  if( !forcedContext && !r.initrender ){\n    r.initrender = true;\n    cy.trigger('initrender');\n  }\n\n  if( !forcedContext ){\n    cy.triggerOnRender();\n  }\n\n};\n\nmodule.exports = CRp;\n\n},{\"../../../math\":79,\"../../../util\":94}],68:[function(_dereq_,module,exports){\n'use strict';\n\n  var math = _dereq_('../../../math');\n\n  var CRp = {};\n\n  // @O Polygon drawing\n  CRp.drawPolygonPath = function(\n    context, x, y, width, height, points) {\n\n    var halfW = width / 2;\n    var halfH = height / 2;\n\n    if( context.beginPath ){ context.beginPath(); }\n\n    context.moveTo( x + halfW * points[0], y + halfH * points[1] );\n\n    for (var i = 1; i < points.length / 2; i++) {\n      context.lineTo( x + halfW * points[i * 2], y + halfH * points[i * 2 + 1] );\n    }\n\n    context.closePath();\n  };\n\n  // Round rectangle drawing\n  CRp.drawRoundRectanglePath = function(\n    context, x, y, width, height, radius) {\n\n    var halfWidth = width / 2;\n    var halfHeight = height / 2;\n    var cornerRadius = math.getRoundRectangleRadius(width, height);\n\n    if( context.beginPath ){ context.beginPath(); }\n\n    // Start at top middle\n    context.moveTo(x, y - halfHeight);\n    // Arc from middle top to right side\n    context.arcTo(x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius);\n    // Arc from right side to bottom\n    context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius);\n    // Arc from bottom to left side\n    context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius);\n    // Arc from left side to topBorder\n    context.arcTo(x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius);\n    // Join line\n    context.lineTo(x, y - halfHeight);\n\n\n    context.closePath();\n  };\n\n  var sin0 = Math.sin(0);\n  var cos0 = Math.cos(0);\n\n  var sin = {};\n  var cos = {};\n\n  var ellipseStepSize = Math.PI / 40;\n\n  for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {\n    sin[i] = Math.sin(i);\n    cos[i] = Math.cos(i);\n  }\n\n  CRp.drawEllipsePath = function(context, centerX, centerY, width, height){\n    if( context.beginPath ){ context.beginPath(); }\n\n    if( context.ellipse ){\n      context.ellipse( centerX, centerY, width/2, height/2, 0, 0, 2*Math.PI );\n    } else {\n      var xPos, yPos;\n      var rw = width/2;\n      var rh = height/2;\n      for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {\n        xPos = centerX - (rw * sin[i]) * sin0 + (rw * cos[i]) * cos0;\n        yPos = centerY + (rh * cos[i]) * sin0 + (rh * sin[i]) * cos0;\n\n        if (i === 0) {\n          context.moveTo(xPos, yPos);\n        } else {\n          context.lineTo(xPos, yPos);\n        }\n      }\n    }\n\n    context.closePath();\n  };\n\nmodule.exports = CRp;\n\n},{\"../../../math\":79}],69:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../../../is');\n\nvar CRp = {};\n\nCRp.createBuffer = function(w, h) {\n  var buffer = document.createElement('canvas');\n  buffer.width = w;\n  buffer.height = h;\n\n  return [buffer, buffer.getContext('2d')];\n};\n\nCRp.bufferCanvasImage = function( options ){\n  var cy = this.cy;\n  var bb = cy.elements().boundingBox();\n  var width = options.full ? Math.ceil(bb.w) : this.container.clientWidth;\n  var height = options.full ? Math.ceil(bb.h) : this.container.clientHeight;\n  var scale = 1;\n\n  if( options.scale !== undefined ){\n    width *= options.scale;\n    height *= options.scale;\n\n    scale = options.scale;\n  } else if( is.number(options.maxWidth) || is.number(options.maxHeight) ){\n    var maxScaleW = Infinity;\n    var maxScaleH = Infinity;\n\n    if( is.number(options.maxWidth) ){\n      maxScaleW = scale * options.maxWidth / width;\n    }\n\n    if( is.number(options.maxHeight) ){\n      maxScaleH = scale * options.maxHeight / height;\n    }\n\n    scale = Math.min( maxScaleW, maxScaleH );\n\n    width *= scale;\n    height *= scale;\n  }\n\n  var buffCanvas = document.createElement('canvas');\n\n  buffCanvas.width = width;\n  buffCanvas.height = height;\n\n  buffCanvas.style.width = width + 'px';\n  buffCanvas.style.height = height + 'px';\n\n  var buffCxt = buffCanvas.getContext('2d');\n\n  // Rasterize the layers, but only if container has nonzero size\n  if (width > 0 && height > 0) {\n\n    buffCxt.clearRect( 0, 0, width, height );\n\n    if( options.bg ){\n      buffCxt.fillStyle = options.bg;\n      buffCxt.rect( 0, 0, width, height );\n      buffCxt.fill();\n    }\n\n    buffCxt.globalCompositeOperation = 'source-over';\n\n    if( options.full ){ // draw the full bounds of the graph\n      this.render({\n        forcedContext: buffCxt,\n        drawAllLayers: true,\n        forcedZoom: scale,\n        forcedPan: { x: -bb.x1*scale, y: -bb.y1*scale },\n        forcedPxRatio: 1\n      });\n    } else { // draw the current view\n      var cyPan = cy.pan();\n      var pan = {\n        x: cyPan.x * scale,\n        y: cyPan.y * scale\n      };\n      var zoom = cy.zoom() * scale;\n\n      this.render({\n        forcedContext: buffCxt,\n        drawAllLayers: true,\n        forcedZoom: zoom,\n        forcedPan: pan,\n        forcedPxRatio: 1\n      });\n    }\n  }\n\n  return buffCanvas;\n};\n\nCRp.png = function( options ){\n  return this.bufferCanvasImage( options ).toDataURL('image/png');\n};\n\nCRp.jpg = function( options ){\n  return this.bufferCanvasImage( options ).toDataURL('image/jpeg');\n};\n\nmodule.exports = CRp;\n\n},{\"../../../is\":77}],70:[function(_dereq_,module,exports){\n/*\nThe canvas renderer was written by Yue Dong.\n\nModifications tracked on Github.\n*/\n\n'use strict';\n\nvar util = _dereq_('../../../util');\nvar is = _dereq_('../../../is');\n\nvar CR = CanvasRenderer;\nvar CRp = CanvasRenderer.prototype;\n\nCRp.CANVAS_LAYERS = 3;\n//\nCRp.SELECT_BOX = 0;\nCRp.DRAG = 1;\nCRp.NODE = 2;\n\nCRp.BUFFER_COUNT = 3;\n//\nCRp.TEXTURE_BUFFER = 0;\nCRp.MOTIONBLUR_BUFFER_NODE = 1;\nCRp.MOTIONBLUR_BUFFER_DRAG = 2;\n\nfunction CanvasRenderer(options) {\n  var r = this;\n\n  r.data = {\n    canvases: new Array(CRp.CANVAS_LAYERS),\n    contexts: new Array(CRp.CANVAS_LAYERS),\n    canvasNeedsRedraw: new Array(CRp.CANVAS_LAYERS),\n\n    bufferCanvases: new Array(CRp.BUFFER_COUNT),\n    bufferContexts: new Array(CRp.CANVAS_LAYERS)\n  };\n\n  r.data.canvasContainer = document.createElement('div');\n  var containerStyle = r.data.canvasContainer.style;\n  r.data.canvasContainer.setAttribute('style', '-webkit-tap-highlight-color: rgba(0,0,0,0);');\n  containerStyle.position = 'relative';\n  containerStyle.zIndex = '0';\n  containerStyle.overflow = 'hidden';\n\n  var container = options.cy.container();\n  container.appendChild( r.data.canvasContainer );\n  container.setAttribute('style', ( container.getAttribute('style') || '' ) + '-webkit-tap-highlight-color: rgba(0,0,0,0);');\n\n  for (var i = 0; i < CRp.CANVAS_LAYERS; i++) {\n    var canvas = r.data.canvases[i] = document.createElement('canvas');\n    r.data.contexts[i] = canvas.getContext('2d');\n    canvas.setAttribute( 'style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + ( is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : '' ) );\n    canvas.style.position = 'absolute';\n    canvas.setAttribute('data-id', 'layer' + i);\n    canvas.style.zIndex = String(CRp.CANVAS_LAYERS - i);\n    r.data.canvasContainer.appendChild(canvas);\n\n    r.data.canvasNeedsRedraw[i] = false;\n  }\n  r.data.topCanvas = r.data.canvases[0];\n\n  r.data.canvases[CRp.NODE].setAttribute('data-id', 'layer' + CRp.NODE + '-node');\n  r.data.canvases[CRp.SELECT_BOX].setAttribute('data-id', 'layer' + CRp.SELECT_BOX + '-selectbox');\n  r.data.canvases[CRp.DRAG].setAttribute('data-id', 'layer' + CRp.DRAG + '-drag');\n\n  for (var i = 0; i < CRp.BUFFER_COUNT; i++) {\n    r.data.bufferCanvases[i] = document.createElement('canvas');\n    r.data.bufferContexts[i] = r.data.bufferCanvases[i].getContext('2d');\n    r.data.bufferCanvases[i].style.position = 'absolute';\n    r.data.bufferCanvases[i].setAttribute('data-id', 'buffer' + i);\n    r.data.bufferCanvases[i].style.zIndex = String(-i - 1);\n    r.data.bufferCanvases[i].style.visibility = 'hidden';\n    //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]);\n  }\n\n  r.pathsEnabled = true;\n}\n\nCRp.redrawHint = function( group, bool ){\n  var r = this;\n\n  switch( group ){\n    case 'eles':\n      r.data.canvasNeedsRedraw[ CRp.NODE ] = bool;\n      break;\n    case 'drag':\n      r.data.canvasNeedsRedraw[ CRp.DRAG ] = bool;\n      break;\n    case 'select':\n      r.data.canvasNeedsRedraw[ CRp.SELECT_BOX ] = bool;\n      break;\n  }\n};\n\n// whether to use Path2D caching for drawing\nvar pathsImpld = typeof Path2D !== 'undefined';\n\nCRp.path2dEnabled = function( on ){\n  if( on === undefined ){\n    return this.pathsEnabled;\n  }\n\n  this.pathsEnabled = on ? true : false;\n};\n\nCRp.usePaths = function(){\n  return pathsImpld && this.pathsEnabled;\n};\n\n[\n  _dereq_('./arrow-shapes'),\n  _dereq_('./drawing-edges'),\n  _dereq_('./drawing-images'),\n  _dereq_('./drawing-label-text'),\n  _dereq_('./drawing-nodes'),\n  _dereq_('./drawing-redraw'),\n  _dereq_('./drawing-shapes'),\n  _dereq_('./export-image'),\n  _dereq_('./node-shapes')\n].forEach(function( props ){\n  util.extend( CRp, props );\n});\n\nmodule.exports = CR;\n\n},{\"../../../is\":77,\"../../../util\":94,\"./arrow-shapes\":62,\"./drawing-edges\":63,\"./drawing-images\":64,\"./drawing-label-text\":65,\"./drawing-nodes\":66,\"./drawing-redraw\":67,\"./drawing-shapes\":68,\"./export-image\":69,\"./node-shapes\":71}],71:[function(_dereq_,module,exports){\n'use strict';\n\nvar CRp = {};\n\nvar impl;\n\nCRp.nodeShapeImpl = function( name ){\n  var self = this;\n\n  return ( impl || (impl = {\n    'ellipse': function( context, centerX, centerY, width, height ){\n      self.drawEllipsePath( context, centerX, centerY, width, height );\n    },\n\n    'polygon': function( context, centerX, centerY, width, height, points ){\n      self.drawPolygonPath( context, centerX, centerY, width, height, points );\n    },\n\n    'roundrectangle': function( context, centerX, centerY, width, height ){\n      self.drawRoundRectanglePath( context, centerX, centerY, width, height, 10 );\n    }\n  }) )[ name ];\n};\n\nmodule.exports = CRp;\n\n},{}],72:[function(_dereq_,module,exports){\n'use strict';\n\nmodule.exports = [\n  { name: 'null', impl: _dereq_('./null') },\n  { name: 'base', impl: _dereq_('./base') },\n  { name: 'canvas', impl: _dereq_('./canvas') }\n];\n\n},{\"./base\":58,\"./canvas\":70,\"./null\":73}],73:[function(_dereq_,module,exports){\n'use strict';\n\nfunction NullRenderer(options){\n  this.options = options;\n  this.notifications = 0; // for testing\n}\n\nvar noop = function(){};\n\nNullRenderer.prototype = {\n  recalculateRenderedStyle: noop,\n  notify: function(){ this.notifications++; },\n  init: noop\n};\n\nmodule.exports = NullRenderer;\n\n},{}],74:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('./is');\nvar util = _dereq_('./util');\nvar Thread = _dereq_('./thread');\nvar Promise = _dereq_('./promise');\nvar define = _dereq_('./define');\n\nvar Fabric = function( N ){\n  if( !(this instanceof Fabric) ){\n    return new Fabric( N );\n  }\n\n  this._private = {\n    pass: []\n  };\n\n  var defN = 4;\n\n  if( is.number(N) ){\n    // then use the specified number of threads\n  } if( typeof navigator !== 'undefined' && navigator.hardwareConcurrency != null ){\n    N = navigator.hardwareConcurrency;\n  } else {\n    try{\n      N = _dereq_('os').cpus().length;\n    } catch( err ){\n      N = defN;\n    }\n  } // TODO could use an estimation here but would the additional expense be worth it?\n\n  for( var i = 0; i < N; i++ ){\n    this[i] = new Thread();\n  }\n\n  this.length = N;\n};\n\nvar fabfn = Fabric.prototype; // short alias\n\nutil.extend(fabfn, {\n\n  instanceString: function(){ return 'fabric'; },\n\n  // require fn in all threads\n  require: function( fn, as ){\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n\n      thread.require( fn, as );\n    }\n\n    return this;\n  },\n\n  // get a random thread\n  random: function(){\n    var i = Math.round( (this.length - 1) * Math.random() );\n    var thread = this[i];\n\n    return thread;\n  },\n\n  // run on random thread\n  run: function( fn ){\n    var pass = this._private.pass.shift();\n\n    return this.random().pass( pass ).run( fn );\n  },\n\n  // sends a random thread a message\n  message: function( m ){\n    return this.random().message( m );\n  },\n\n  // send all threads a message\n  broadcast: function( m ){\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n\n      thread.message( m );\n    }\n\n    return this; // chaining\n  },\n\n  // stop all threads\n  stop: function(){\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n\n      thread.stop();\n    }\n\n    return this; // chaining\n  },\n\n  // pass data to be used with .spread() etc.\n  pass: function( data ){\n    var pass = this._private.pass;\n\n    if( is.array(data) ){\n      pass.push( data );\n    } else {\n      throw 'Only arrays may be used with fabric.pass()';\n    }\n\n    return this; // chaining\n  },\n\n  spreadSize: function(){\n    var subsize =  Math.ceil( this._private.pass[0].length / this.length );\n\n    subsize = Math.max( 1, subsize ); // don't pass less than one ele to each thread\n\n    return subsize;\n  },\n\n  // split the data into slices to spread the data equally among threads\n  spread: function( fn ){\n    var self = this;\n    var _p = self._private;\n    var subsize = self.spreadSize(); // number of pass eles to handle in each thread\n    var pass = _p.pass.shift().concat([]); // keep a copy\n    var runPs = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n      var slice = pass.splice( 0, subsize );\n\n      var runP = thread.pass( slice ).run( fn );\n\n      runPs.push( runP );\n\n      var doneEarly = pass.length === 0;\n      if( doneEarly ){ break; }\n    }\n\n    return Promise.all( runPs ).then(function( thens ){\n      var postpass = [];\n      var p = 0;\n\n      // fill postpass with the total result joined from all threads\n      for( var i = 0; i < thens.length; i++ ){\n        var then = thens[i]; // array result from thread i\n\n        for( var j = 0; j < then.length; j++ ){\n          var t = then[j]; // array element\n\n          postpass[ p++ ] = t;\n        }\n      }\n\n      return postpass;\n    });\n  },\n\n  // parallel version of array.map()\n  map: function( fn ){\n    var self = this;\n\n    self.require( fn, '_$_$_fabmap' );\n\n    return self.spread(function( split ){\n      var mapped = [];\n      var origResolve = resolve; // jshint ignore:line\n\n      resolve = function( val ){ // jshint ignore:line\n        mapped.push( val );\n      };\n\n      for( var i = 0; i < split.length; i++ ){\n        var oldLen = mapped.length;\n        var ret = _$_$_fabmap( split[i] ); // jshint ignore:line\n        var nothingInsdByResolve = oldLen === mapped.length;\n\n        if( nothingInsdByResolve ){\n          mapped.push( ret );\n        }\n      }\n\n      resolve = origResolve; // jshint ignore:line\n\n      return mapped;\n    });\n\n  },\n\n  // parallel version of array.filter()\n  filter: function( fn ){\n    var _p = this._private;\n    var pass = _p.pass[0];\n\n    return this.map( fn ).then(function( include ){\n      var ret = [];\n\n      for( var i = 0; i < pass.length; i++ ){\n        var datum = pass[i];\n        var incDatum = include[i];\n\n        if( incDatum ){\n          ret.push( datum );\n        }\n      }\n\n      return ret;\n    });\n  },\n\n  // sorts the passed array using a divide and conquer strategy\n  sort: function( cmp ){\n    var self = this;\n    var P = this._private.pass[0].length;\n    var subsize = this.spreadSize();\n\n    cmp = cmp || function( a, b ){ // default comparison function\n      if( a < b ){\n        return -1;\n      } else if( a > b ){\n        return 1;\n      }\n\n      return 0;\n    };\n\n    self.require( cmp, '_$_$_cmp' );\n\n    return self.spread(function( split ){ // sort each split normally\n      var sortedSplit = split.sort( _$_$_cmp ); // jshint ignore:line\n      resolve( sortedSplit ); // jshint ignore:line\n\n    }).then(function( joined ){\n      // do all the merging in the main thread to minimise data transfer\n\n      // TODO could do merging in separate threads but would incur add'l cost of data transfer\n      // for each level of the merge\n\n      var merge = function( i, j, max ){\n        // don't overflow array\n        j = Math.min( j, P );\n        max = Math.min( max, P );\n\n        // left and right sides of merge\n        var l = i;\n        var r = j;\n\n        var sorted = [];\n\n        for( var k = l; k < max; k++ ){\n\n          var eleI = joined[i];\n          var eleJ = joined[j];\n\n          if( i < r && ( j >= max || cmp(eleI, eleJ) <= 0 ) ){\n            sorted.push( eleI );\n            i++;\n          } else {\n            sorted.push( eleJ );\n            j++;\n          }\n\n        }\n\n        // in the array proper, put the sorted values\n        for( var k = 0; k < sorted.length; k++ ){ // kth sorted item\n          var index = l + k;\n\n          joined[ index ] = sorted[k];\n        }\n      };\n\n      for( var splitL = subsize; splitL < P; splitL *= 2 ){ // merge until array is \"split\" as 1\n\n        for( var i = 0; i < P; i += 2*splitL ){\n          merge( i, i + splitL, i + 2*splitL );\n        }\n\n      }\n\n      return joined;\n    });\n  }\n\n\n});\n\nvar defineRandomPasser = function( opts ){\n  opts = opts || {};\n\n  return function( fn, arg1 ){\n    var pass = this._private.pass.shift();\n\n    return this.random().pass( pass )[ opts.threadFn ]( fn, arg1 );\n  };\n};\n\nutil.extend(fabfn, {\n  randomMap: defineRandomPasser({ threadFn: 'map' }),\n\n  reduce: defineRandomPasser({ threadFn: 'reduce' }),\n\n  reduceRight: defineRandomPasser({ threadFn: 'reduceRight' })\n});\n\n// aliases\nvar fn = fabfn;\nfn.promise = fn.run;\nfn.terminate = fn.halt = fn.stop;\nfn.include = fn.require;\n\n// pull in event apis\nutil.extend(fabfn, {\n  on: define.on(),\n  one: define.on({ unbindSelfOnTrigger: true }),\n  off: define.off(),\n  trigger: define.trigger()\n});\n\ndefine.eventAliasesOn( fabfn );\n\nmodule.exports = Fabric;\n\n},{\"./define\":41,\"./is\":77,\"./promise\":80,\"./thread\":92,\"./util\":94,\"os\":undefined}],75:[function(_dereq_,module,exports){\n'use strict';\n/* jshint ignore:start */\n\n// Generated by CoffeeScript 1.8.0\n(function() {\n  var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;\n\n  floor = Math.floor, min = Math.min;\n\n\n  /*\n  Default comparison function to be used\n   */\n\n  defaultCmp = function(x, y) {\n    if (x < y) {\n      return -1;\n    }\n    if (x > y) {\n      return 1;\n    }\n    return 0;\n  };\n\n\n  /*\n  Insert item x in list a, and keep it sorted assuming a is sorted.\n\n  If x is already in a, insert it to the right of the rightmost x.\n\n  Optional args lo (default 0) and hi (default a.length) bound the slice\n  of a to be searched.\n   */\n\n  insort = function(a, x, lo, hi, cmp) {\n    var mid;\n    if (lo == null) {\n      lo = 0;\n    }\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (lo < 0) {\n      throw new Error('lo must be non-negative');\n    }\n    if (hi == null) {\n      hi = a.length;\n    }\n    while (lo < hi) {\n      mid = floor((lo + hi) / 2);\n      if (cmp(x, a[mid]) < 0) {\n        hi = mid;\n      } else {\n        lo = mid + 1;\n      }\n    }\n    return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);\n  };\n\n\n  /*\n  Push item onto heap, maintaining the heap invariant.\n   */\n\n  heappush = function(array, item, cmp) {\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    array.push(item);\n    return _siftdown(array, 0, array.length - 1, cmp);\n  };\n\n\n  /*\n  Pop the smallest item off the heap, maintaining the heap invariant.\n   */\n\n  heappop = function(array, cmp) {\n    var lastelt, returnitem;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    lastelt = array.pop();\n    if (array.length) {\n      returnitem = array[0];\n      array[0] = lastelt;\n      _siftup(array, 0, cmp);\n    } else {\n      returnitem = lastelt;\n    }\n    return returnitem;\n  };\n\n\n  /*\n  Pop and return the current smallest value, and add the new item.\n\n  This is more efficient than heappop() followed by heappush(), and can be\n  more appropriate when using a fixed size heap. Note that the value\n  returned may be larger than item! That constrains reasonable use of\n  this routine unless written as part of a conditional replacement:\n      if item > array[0]\n        item = heapreplace(array, item)\n   */\n\n  heapreplace = function(array, item, cmp) {\n    var returnitem;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    returnitem = array[0];\n    array[0] = item;\n    _siftup(array, 0, cmp);\n    return returnitem;\n  };\n\n\n  /*\n  Fast version of a heappush followed by a heappop.\n   */\n\n  heappushpop = function(array, item, cmp) {\n    var _ref;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (array.length && cmp(array[0], item) < 0) {\n      _ref = [array[0], item], item = _ref[0], array[0] = _ref[1];\n      _siftup(array, 0, cmp);\n    }\n    return item;\n  };\n\n\n  /*\n  Transform list into a heap, in-place, in O(array.length) time.\n   */\n\n  heapify = function(array, cmp) {\n    var i, _i, _j, _len, _ref, _ref1, _results, _results1;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    _ref1 = (function() {\n      _results1 = [];\n      for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }\n      return _results1;\n    }).apply(this).reverse();\n    _results = [];\n    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n      i = _ref1[_i];\n      _results.push(_siftup(array, i, cmp));\n    }\n    return _results;\n  };\n\n\n  /*\n  Update the position of the given item in the heap.\n  This function should be called every time the item is being modified.\n   */\n\n  updateItem = function(array, item, cmp) {\n    var pos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    pos = array.indexOf(item);\n    if (pos === -1) {\n      return;\n    }\n    _siftdown(array, 0, pos, cmp);\n    return _siftup(array, pos, cmp);\n  };\n\n\n  /*\n  Find the n largest elements in a dataset.\n   */\n\n  nlargest = function(array, n, cmp) {\n    var elem, result, _i, _len, _ref;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    result = array.slice(0, n);\n    if (!result.length) {\n      return result;\n    }\n    heapify(result, cmp);\n    _ref = array.slice(n);\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      elem = _ref[_i];\n      heappushpop(result, elem, cmp);\n    }\n    return result.sort(cmp).reverse();\n  };\n\n\n  /*\n  Find the n smallest elements in a dataset.\n   */\n\n  nsmallest = function(array, n, cmp) {\n    var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (n * 10 <= array.length) {\n      result = array.slice(0, n).sort(cmp);\n      if (!result.length) {\n        return result;\n      }\n      los = result[result.length - 1];\n      _ref = array.slice(n);\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        elem = _ref[_i];\n        if (cmp(elem, los) < 0) {\n          insort(result, elem, 0, null, cmp);\n          result.pop();\n          los = result[result.length - 1];\n        }\n      }\n      return result;\n    }\n    heapify(array, cmp);\n    _results = [];\n    for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {\n      _results.push(heappop(array, cmp));\n    }\n    return _results;\n  };\n\n  _siftdown = function(array, startpos, pos, cmp) {\n    var newitem, parent, parentpos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    newitem = array[pos];\n    while (pos > startpos) {\n      parentpos = (pos - 1) >> 1;\n      parent = array[parentpos];\n      if (cmp(newitem, parent) < 0) {\n        array[pos] = parent;\n        pos = parentpos;\n        continue;\n      }\n      break;\n    }\n    return array[pos] = newitem;\n  };\n\n  _siftup = function(array, pos, cmp) {\n    var childpos, endpos, newitem, rightpos, startpos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    endpos = array.length;\n    startpos = pos;\n    newitem = array[pos];\n    childpos = 2 * pos + 1;\n    while (childpos < endpos) {\n      rightpos = childpos + 1;\n      if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {\n        childpos = rightpos;\n      }\n      array[pos] = array[childpos];\n      pos = childpos;\n      childpos = 2 * pos + 1;\n    }\n    array[pos] = newitem;\n    return _siftdown(array, startpos, pos, cmp);\n  };\n\n  Heap = (function() {\n    Heap.push = heappush;\n\n    Heap.pop = heappop;\n\n    Heap.replace = heapreplace;\n\n    Heap.pushpop = heappushpop;\n\n    Heap.heapify = heapify;\n\n    Heap.updateItem = updateItem;\n\n    Heap.nlargest = nlargest;\n\n    Heap.nsmallest = nsmallest;\n\n    function Heap(cmp) {\n      this.cmp = cmp != null ? cmp : defaultCmp;\n      this.nodes = [];\n    }\n\n    Heap.prototype.push = function(x) {\n      return heappush(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.pop = function() {\n      return heappop(this.nodes, this.cmp);\n    };\n\n    Heap.prototype.peek = function() {\n      return this.nodes[0];\n    };\n\n    Heap.prototype.contains = function(x) {\n      return this.nodes.indexOf(x) !== -1;\n    };\n\n    Heap.prototype.replace = function(x) {\n      return heapreplace(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.pushpop = function(x) {\n      return heappushpop(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.heapify = function() {\n      return heapify(this.nodes, this.cmp);\n    };\n\n    Heap.prototype.updateItem = function(x) {\n      return updateItem(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.clear = function() {\n      return this.nodes = [];\n    };\n\n    Heap.prototype.empty = function() {\n      return this.nodes.length === 0;\n    };\n\n    Heap.prototype.size = function() {\n      return this.nodes.length;\n    };\n\n    Heap.prototype.clone = function() {\n      var heap;\n      heap = new Heap();\n      heap.nodes = this.nodes.slice(0);\n      return heap;\n    };\n\n    Heap.prototype.toArray = function() {\n      return this.nodes.slice(0);\n    };\n\n    Heap.prototype.insert = Heap.prototype.push;\n\n    Heap.prototype.top = Heap.prototype.peek;\n\n    Heap.prototype.front = Heap.prototype.peek;\n\n    Heap.prototype.has = Heap.prototype.contains;\n\n    Heap.prototype.copy = Heap.prototype.clone;\n\n    return Heap;\n\n  })();\n\n  (function(root, factory) {\n    if (typeof define === 'function' && define.amd) {\n      return define([], factory);\n    } else if (typeof exports === 'object') {\n      return module.exports = factory();\n    } else {\n      return root.Heap = factory();\n    }\n  })(this, function() {\n    return Heap;\n  });\n\n}).call(this);\n\n/* jshint ignore:end */\n\n},{}],76:[function(_dereq_,module,exports){\n'use strict';\n\nvar window = _dereq_('./window');\nvar is = _dereq_('./is');\nvar Core = _dereq_('./core');\nvar extension = _dereq_('./extension');\nvar registerJquery = _dereq_('./jquery-plugin');\nvar Stylesheet = _dereq_('./stylesheet');\nvar Thread = _dereq_('./thread');\nvar Fabric = _dereq_('./fabric');\n\nvar cytoscape = function( options ){ // jshint ignore:line\n  // if no options specified, use default\n  if( options === undefined ){\n    options = {};\n  }\n\n  // create instance\n  if( is.plainObject( options ) ){\n    return new Core( options );\n  }\n\n  // allow for registration of extensions\n  else if( is.string( options ) ) {\n    return extension.apply(extension, arguments);\n  }\n};\n\n// replaced by build system\ncytoscape.version = '2.5.3';\n\n// try to register w/ jquery\nif( window && window.jQuery ){\n  registerJquery( window.jQuery, cytoscape );\n}\n\n// expose register api\ncytoscape.registerJquery = function( jQuery ){\n  registerJquery( jQuery, cytoscape );\n};\n\n// expose public apis (mostly for extensions)\ncytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet;\ncytoscape.thread = cytoscape.Thread = Thread;\ncytoscape.fabric = cytoscape.Fabric = Fabric;\n\nmodule.exports = cytoscape;\n\n},{\"./core\":34,\"./extension\":43,\"./fabric\":74,\"./is\":77,\"./jquery-plugin\":78,\"./stylesheet\":91,\"./thread\":92,\"./window\":100}],77:[function(_dereq_,module,exports){\n'use strict';\n\nvar window = _dereq_('./window');\nvar navigator = window ? window.navigator : null;\n\nvar typeofstr = typeof '';\nvar typeofobj = typeof {};\nvar typeoffn = typeof function(){};\nvar typeofhtmlele = typeof HTMLElement;\n\nvar instanceStr = function( obj ){\n  return obj && obj.instanceString && is.fn( obj.instanceString ) ? obj.instanceString() : null;\n};\n\nvar is = {\n  defined: function(obj){\n    return obj != null; // not undefined or null\n  },\n\n  string: function(obj){\n    return obj != null && typeof obj == typeofstr;\n  },\n\n  fn: function(obj){\n    return obj != null && typeof obj === typeoffn;\n  },\n\n  array: function(obj){\n    return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;\n  },\n\n  plainObject: function(obj){\n    return obj != null && typeof obj === typeofobj && !is.array(obj) && obj.constructor === Object;\n  },\n\n  object: function(obj){\n    return obj != null && typeof obj === typeofobj;\n  },\n\n  number: function(obj){\n    return obj != null && typeof obj === typeof 1 && !isNaN(obj);\n  },\n\n  integer: function( obj ){\n    return is.number(obj) && Math.floor(obj) === obj;\n  },\n\n  bool: function(obj){\n    return obj != null && typeof obj === typeof true;\n  },\n\n  htmlElement: function(obj){\n    if( 'undefined' === typeofhtmlele ){\n      return undefined;\n    } else {\n      return null != obj && obj instanceof HTMLElement;\n    }\n  },\n\n  elementOrCollection: function(obj){\n    return is.element(obj) || is.collection(obj);\n  },\n\n  element: function(obj){\n    return instanceStr(obj) === 'collection' && obj._private.single;\n  },\n\n  collection: function(obj){\n    return instanceStr(obj) === 'collection' && !obj._private.single;\n  },\n\n  core: function(obj){\n    return instanceStr(obj) === 'core';\n  },\n\n  style: function(obj){\n    return instanceStr(obj) === 'style';\n  },\n\n  stylesheet: function(obj){\n    return instanceStr(obj) === 'stylesheet';\n  },\n\n  event: function(obj){\n    return instanceStr(obj) === 'event';\n  },\n\n  thread: function(obj){\n    return instanceStr(obj) === 'thread';\n  },\n\n  fabric: function(obj){\n    return instanceStr(obj) === 'fabric';\n  },\n\n  emptyString: function(obj){\n    if( !obj ){ // null is empty\n      return true;\n    } else if( is.string(obj) ){\n      if( obj === '' || obj.match(/^\\s+$/) ){\n        return true; // empty string is empty\n      }\n    }\n\n    return false; // otherwise, we don't know what we've got\n  },\n\n  nonemptyString: function(obj){\n    if( obj && is.string(obj) && obj !== '' && !obj.match(/^\\s+$/) ){\n      return true;\n    }\n\n    return false;\n  },\n\n  domElement: function(obj){\n    if( typeof HTMLElement === 'undefined' ){\n      return false; // we're not in a browser so it doesn't matter\n    } else {\n      return obj instanceof HTMLElement;\n    }\n  },\n\n  boundingBox: function(obj){\n    return is.plainObject(obj) &&\n      is.number(obj.x1) && is.number(obj.x2) &&\n      is.number(obj.y1) && is.number(obj.y2)\n    ;\n  },\n\n  promise: function(obj){\n    return is.object(obj) && is.fn(obj.then);\n  },\n\n  touch: function(){\n    return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch );\n  },\n\n  gecko: function(){\n    return typeof InstallTrigger !== 'undefined' || ('MozAppearance' in document.documentElement.style);\n  },\n\n  webkit: function(){\n    return typeof webkitURL !== 'undefined' || ('WebkitAppearance' in document.documentElement.style);\n  },\n\n  chromium: function(){\n    return typeof chrome !== 'undefined';\n  },\n\n  khtml: function(){\n    return navigator && navigator.vendor.match(/kde/i); // probably a better way to detect this...\n  },\n\n  khtmlEtc: function(){\n    return is.khtml() || is.webkit() || is.chromium();\n  },\n\n  ms: function(){\n     return navigator && navigator.userAgent.match(/msie|trident|edge/i); // probably a better way to detect this...\n  },\n\n  windows: function(){\n    return navigator && navigator.appVersion.match(/Win/i);\n  },\n\n  mac: function(){\n    return navigator && navigator.appVersion.match(/Mac/i);\n  },\n\n  linux: function(){\n    return navigator && navigator.appVersion.match(/Linux/i);\n  },\n\n  unix: function(){\n    return navigator && navigator.appVersion.match(/X11/i);\n  }\n};\n\nmodule.exports = is;\n\n},{\"./window\":100}],78:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('./is');\n\nvar cyReg = function( $ele ){\n  var d = $ele[0]._cyreg = $ele[0]._cyreg || {};\n\n  return d;\n};\n\nvar registerJquery = function( $, cytoscape ){\n  if( !$ ){ return; } // no jquery => don't need this\n\n  if( $.fn.cytoscape ){ return; } // already registered\n\n  // allow calls on a jQuery selector by proxying calls to $.cytoscape\n  // e.g. $(\"#foo\").cytoscape(options) => $.cytoscape(options) on #foo\n  $.fn.cytoscape = function(opts){\n    var $this = $(this);\n\n    // get object\n    if( opts === 'get' ){\n      return cyReg( $this ).cy;\n    }\n\n    // bind to ready\n    else if( is.fn(opts) ){\n\n      var ready = opts;\n      var cy = cyReg( $this ).cy;\n\n      if( cy && cy.isReady() ){ // already ready so just trigger now\n        cy.trigger('ready', [], ready);\n\n      } else { // not yet ready, so add to readies list\n        var data = cyReg( $this );\n        var readies = data.readies = data.readies || [];\n\n        readies.push( ready );\n      }\n\n    }\n\n    // proxy to create instance\n    else if( is.plainObject(opts) ){\n      return $this.each(function(){\n        var options = $.extend({}, opts, {\n          container: $(this)[0]\n        });\n\n        cytoscape(options);\n      });\n    }\n  };\n\n  // allow access to the global cytoscape object under jquery for legacy reasons\n  $.cytoscape = cytoscape;\n\n  // use short alias (cy) if not already defined\n  if( $.fn.cy == null && $.cy == null ){\n    $.fn.cy = $.fn.cytoscape;\n    $.cy = $.cytoscape;\n  }\n};\n\nmodule.exports = registerJquery;\n\n},{\"./is\":77}],79:[function(_dereq_,module,exports){\n'use strict';\n\nvar math = {};\n\nmath.signum = function(x){\n  if( x > 0 ){\n    return 1;\n  } else if( x < 0 ){\n    return -1;\n  } else {\n    return 0;\n  }\n};\n\nmath.distance = function( p1, p2 ){\n  return Math.sqrt( math.sqDistance(p1, p2) );\n};\n\nmath.sqDistance = function( p1, p2 ){\n  var dx = p2.x - p1.x;\n  var dy = p2.y - p1.y;\n\n  return dx*dx + dy*dy;\n};\n\n// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves\nmath.qbezierAt = function(p0, p1, p2, t){\n  return (1 - t)*(1 - t)*p0 + 2*(1 - t)*t*p1 + t*t*p2;\n};\n\nmath.qbezierPtAt = function(p0, p1, p2, t){\n  return {\n    x: math.qbezierAt( p0.x, p1.x, p2.x, t ),\n    y: math.qbezierAt( p0.y, p1.y, p2.y, t )\n  };\n};\n\n// makes a full bb (x1, y1, x2, y2, w, h) from implicit params\nmath.makeBoundingBox = function( bb ){\n  if( bb.x1 != null && bb.y1 != null ){\n    if( bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1 ){\n      return {\n        x1: bb.x1,\n        y1: bb.y1,\n        x2: bb.x2,\n        y2: bb.y2,\n        w: bb.x2 - bb.x1,\n        h: bb.y2 - bb.y1\n      };\n    } else if( bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0 ){\n      return {\n        x1: bb.x1,\n        y1: bb.y1,\n        x2: bb.x1 + bb.w,\n        y2: bb.y1 + bb.h,\n        w: bb.w,\n        h: bb.h\n      };\n    }\n  }\n};\n\nmath.boundingBoxesIntersect = function( bb1, bb2 ){\n  // case: one bb to right of other\n  if( bb1.x1 > bb2.x2 ){ return false; }\n  if( bb2.x1 > bb1.x2 ){ return false; }\n\n  // case: one bb to left of other\n  if( bb1.x2 < bb2.x1 ){ return false; }\n  if( bb2.x2 < bb1.x1 ){ return false; }\n\n  // case: one bb above other\n  if( bb1.y2 < bb2.y1 ){ return false; }\n  if( bb2.y2 < bb1.y1 ){ return false; }\n\n  // case: one bb below other\n  if( bb1.y1 > bb2.y2 ){ return false; }\n  if( bb2.y1 > bb1.y2 ){ return false; }\n\n  // otherwise, must have some overlap\n  return true;\n};\n\nmath.inBoundingBox = function( bb, x, y ){\n  return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2;\n};\n\nmath.pointInBoundingBox = function( bb, pt ){\n  return this.inBoundingBox( bb, pt.x, pt.y );\n};\n\nmath.roundRectangleIntersectLine = function(\n  x, y, nodeX, nodeY, width, height, padding) {\n\n  var cornerRadius = this.getRoundRectangleRadius(width, height);\n\n  var halfWidth = width / 2;\n  var halfHeight = height / 2;\n\n  // Check intersections with straight line segments\n  var straightLineIntersections;\n\n  // Top segment, left to right\n  {\n    var topStartX = nodeX - halfWidth + cornerRadius - padding;\n    var topStartY = nodeY - halfHeight - padding;\n    var topEndX = nodeX + halfWidth - cornerRadius + padding;\n    var topEndY = topStartY;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Right segment, top to bottom\n  {\n    var rightStartX = nodeX + halfWidth + padding;\n    var rightStartY = nodeY - halfHeight + cornerRadius - padding;\n    var rightEndX = rightStartX;\n    var rightEndY = nodeY + halfHeight - cornerRadius + padding;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Bottom segment, left to right\n  {\n    var bottomStartX = nodeX - halfWidth + cornerRadius - padding;\n    var bottomStartY = nodeY + halfHeight + padding;\n    var bottomEndX = nodeX + halfWidth - cornerRadius + padding;\n    var bottomEndY = bottomStartY;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Left segment, top to bottom\n  {\n    var leftStartX = nodeX - halfWidth - padding;\n    var leftStartY = nodeY - halfHeight + cornerRadius - padding;\n    var leftEndX = leftStartX;\n    var leftEndY = nodeY + halfHeight - cornerRadius + padding;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Check intersections with arc segments\n  var arcIntersections;\n\n  // Top Left\n  {\n    var topLeftCenterX = nodeX - halfWidth + cornerRadius;\n    var topLeftCenterY = nodeY - halfHeight + cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      topLeftCenterX, topLeftCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] <= topLeftCenterX\n      && arcIntersections[1] <= topLeftCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  // Top Right\n  {\n    var topRightCenterX = nodeX + halfWidth - cornerRadius;\n    var topRightCenterY = nodeY - halfHeight + cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      topRightCenterX, topRightCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] >= topRightCenterX\n      && arcIntersections[1] <= topRightCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  // Bottom Right\n  {\n    var bottomRightCenterX = nodeX + halfWidth - cornerRadius;\n    var bottomRightCenterY = nodeY + halfHeight - cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      bottomRightCenterX, bottomRightCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] >= bottomRightCenterX\n      && arcIntersections[1] >= bottomRightCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  // Bottom Left\n  {\n    var bottomLeftCenterX = nodeX - halfWidth + cornerRadius;\n    var bottomLeftCenterY = nodeY + halfHeight - cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] <= bottomLeftCenterX\n      && arcIntersections[1] >= bottomLeftCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  return []; // if nothing\n};\n\nmath.inLineVicinity = function(x, y, lx1, ly1, lx2, ly2, tolerance){\n  var t = tolerance;\n\n  var x1 = Math.min(lx1, lx2);\n  var x2 = Math.max(lx1, lx2);\n  var y1 = Math.min(ly1, ly2);\n  var y2 = Math.max(ly1, ly2);\n\n  return x1 - t <= x && x <= x2 + t\n    && y1 - t <= y && y <= y2 + t;\n};\n\nmath.inBezierVicinity = function(\n  x, y, x1, y1, x2, y2, x3, y3, tolerance) {\n\n  var bb = {\n    x1: Math.min( x1, x3, x2 ) - tolerance,\n    x2: Math.max( x1, x3, x2 ) + tolerance,\n    y1: Math.min( y1, y3, y2 ) - tolerance,\n    y2: Math.max( y1, y3, y2 ) + tolerance\n  };\n\n  // if outside the rough bounding box for the bezier, then it can't be a hit\n  if( x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2 ){\n    // console.log('bezier out of rough bb')\n    return false;\n  } else {\n    // console.log('do more expensive check');\n    return true;\n  }\n\n};\n\nmath.solveCubic = function(a, b, c, d, result) {\n\n  // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where\n  // r is the real component, i is the imaginary component\n\n  // An implementation of the Cardano method from the year 1545\n  // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots\n\n  b /= a;\n  c /= a;\n  d /= a;\n\n  var discriminant, q, r, dum1, s, t, term1, r13;\n\n  q = (3.0 * c - (b * b)) / 9.0;\n  r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b));\n  r /= 54.0;\n\n  discriminant = q * q * q + r * r;\n  result[1] = 0;\n  term1 = (b / 3.0);\n\n  if (discriminant > 0) {\n    s = r + Math.sqrt(discriminant);\n    s = ((s < 0) ? -Math.pow(-s, (1.0 / 3.0)) : Math.pow(s, (1.0 / 3.0)));\n    t = r - Math.sqrt(discriminant);\n    t = ((t < 0) ? -Math.pow(-t, (1.0 / 3.0)) : Math.pow(t, (1.0 / 3.0)));\n    result[0] = -term1 + s + t;\n    term1 += (s + t) / 2.0;\n    result[4] = result[2] = -term1;\n    term1 = Math.sqrt(3.0) * (-t + s) / 2;\n    result[3] = term1;\n    result[5] = -term1;\n    return;\n  }\n\n  result[5] = result[3] = 0;\n\n  if (discriminant === 0) {\n    r13 = ((r < 0) ? -Math.pow(-r, (1.0 / 3.0)) : Math.pow(r, (1.0 / 3.0)));\n    result[0] = -term1 + 2.0 * r13;\n    result[4] = result[2] = -(r13 + term1);\n    return;\n  }\n\n  q = -q;\n  dum1 = q * q * q;\n  dum1 = Math.acos(r / Math.sqrt(dum1));\n  r13 = 2.0 * Math.sqrt(q);\n  result[0] = -term1 + r13 * Math.cos(dum1 / 3.0);\n  result[2] = -term1 + r13 * Math.cos((dum1 + 2.0 * Math.PI) / 3.0);\n  result[4] = -term1 + r13 * Math.cos((dum1 + 4.0 * Math.PI) / 3.0);\n\n  return;\n};\n\nmath.sqDistanceToQuadraticBezier = function(\n  x, y, x1, y1, x2, y2, x3, y3) {\n\n  // Find minimum distance by using the minimum of the distance\n  // function between the given point and the curve\n\n  // This gives the coefficients of the resulting cubic equation\n  // whose roots tell us where a possible minimum is\n  // (Coefficients are divided by 4)\n\n  var a = 1.0 * x1*x1 - 4*x1*x2 + 2*x1*x3 + 4*x2*x2 - 4*x2*x3 + x3*x3\n    + y1*y1 - 4*y1*y2 + 2*y1*y3 + 4*y2*y2 - 4*y2*y3 + y3*y3;\n\n  var b = 1.0 * 9*x1*x2 - 3*x1*x1 - 3*x1*x3 - 6*x2*x2 + 3*x2*x3\n    + 9*y1*y2 - 3*y1*y1 - 3*y1*y3 - 6*y2*y2 + 3*y2*y3;\n\n  var c = 1.0 * 3*x1*x1 - 6*x1*x2 + x1*x3 - x1*x + 2*x2*x2 + 2*x2*x - x3*x\n    + 3*y1*y1 - 6*y1*y2 + y1*y3 - y1*y + 2*y2*y2 + 2*y2*y - y3*y;\n\n  var d = 1.0 * x1*x2 - x1*x1 + x1*x - x2*x\n    + y1*y2 - y1*y1 + y1*y - y2*y;\n\n  // debug(\"coefficients: \" + a / a + \", \" + b / a + \", \" + c / a + \", \" + d / a);\n\n  var roots = [];\n\n  // Use the cubic solving algorithm\n  this.solveCubic(a, b, c, d, roots);\n\n  var zeroThreshold = 0.0000001;\n\n  var params = [];\n\n  for (var index = 0; index < 6; index += 2) {\n    if (Math.abs(roots[index + 1]) < zeroThreshold\n        && roots[index] >= 0\n        && roots[index] <= 1.0) {\n      params.push(roots[index]);\n    }\n  }\n\n  params.push(1.0);\n  params.push(0.0);\n\n  var minDistanceSquared = -1;\n  var closestParam;\n\n  var curX, curY, distSquared;\n  for (var i = 0; i < params.length; i++) {\n    curX = Math.pow(1.0 - params[i], 2.0) * x1\n      + 2.0 * (1 - params[i]) * params[i] * x2\n      + params[i] * params[i] * x3;\n\n    curY = Math.pow(1 - params[i], 2.0) * y1\n      + 2 * (1.0 - params[i]) * params[i] * y2\n      + params[i] * params[i] * y3;\n\n    distSquared = Math.pow(curX - x, 2) + Math.pow(curY - y, 2);\n    // debug('distance for param ' + params[i] + \": \" + Math.sqrt(distSquared));\n    if (minDistanceSquared >= 0) {\n      if (distSquared < minDistanceSquared) {\n        minDistanceSquared = distSquared;\n        closestParam = params[i];\n      }\n    } else {\n      minDistanceSquared = distSquared;\n      closestParam = params[i];\n    }\n  }\n\n  return minDistanceSquared;\n};\n\nmath.sqDistanceToFiniteLine = function(x, y, x1, y1, x2, y2) {\n  var offset = [x - x1, y - y1];\n  var line = [x2 - x1, y2 - y1];\n\n  var lineSq = line[0] * line[0] + line[1] * line[1];\n  var hypSq = offset[0] * offset[0] + offset[1] * offset[1];\n\n  var dotProduct = offset[0] * line[0] + offset[1] * line[1];\n  var adjSq = dotProduct * dotProduct / lineSq;\n\n  if (dotProduct < 0) {\n    return hypSq;\n  }\n\n  if (adjSq > lineSq) {\n    return (x - x2) * (x - x2) + (y - y2) * (y - y2);\n  }\n\n  return hypSq - adjSq;\n};\n\nmath.pointInsidePolygonPoints = function(x, y, points){\n  var x1, y1, x2, y2;\n  var y3;\n\n  // Intersect with vertical line through (x, y)\n  var up = 0;\n  var down = 0;\n  for (var i = 0; i < points.length / 2; i++) {\n\n    x1 = points[i * 2];\n    y1 = points[i * 2 + 1];\n\n    if (i + 1 < points.length / 2) {\n      x2 = points[(i + 1) * 2];\n      y2 = points[(i + 1) * 2 + 1];\n    } else {\n      x2 = points[(i + 1 - points.length / 2) * 2];\n      y2 = points[(i + 1 - points.length / 2) * 2 + 1];\n    }\n\n    if (x1 == x && x2 == x) {\n\n    } else if ((x1 >= x && x >= x2)\n      || (x1 <= x && x <= x2)) {\n\n      y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1;\n\n      if (y3 > y) {\n        up++;\n      }\n\n      if (y3 < y) {\n        down++;\n      }\n\n    } else {\n      continue;\n    }\n\n  }\n\n  if (up % 2 === 0) {\n    return false;\n  } else {\n    return true;\n  }\n};\n\nmath.pointInsidePolygon = function(\n  x, y, basePoints, centerX, centerY, width, height, direction, padding) {\n\n  //var direction = arguments[6];\n  var transformedPoints = new Array(basePoints.length);\n\n  // Gives negative angle\n  var angle;\n\n  if( direction[0] != null ){\n    angle = Math.atan(direction[1] / direction[0]);\n\n    if (direction[0] < 0) {\n      angle = angle + Math.PI / 2;\n    } else {\n      angle = -angle - Math.PI / 2;\n    }\n  } else {\n    angle = direction;\n  }\n\n  var cos = Math.cos(-angle);\n  var sin = Math.sin(-angle);\n\n  //    console.log(\"base: \" + basePoints);\n  for (var i = 0; i < transformedPoints.length / 2; i++) {\n    transformedPoints[i * 2] =\n      width / 2 * (basePoints[i * 2] * cos\n        - basePoints[i * 2 + 1] * sin);\n\n    transformedPoints[i * 2 + 1] =\n      height / 2 * (basePoints[i * 2 + 1] * cos\n        + basePoints[i * 2] * sin);\n\n    transformedPoints[i * 2] += centerX;\n    transformedPoints[i * 2 + 1] += centerY;\n  }\n\n  var points;\n\n  if (padding > 0) {\n    var expandedLineSet = this.expandPolygon(\n      transformedPoints,\n      -padding);\n\n    points = this.joinLines(expandedLineSet);\n  } else {\n    points = transformedPoints;\n  }\n\n  return math.pointInsidePolygonPoints( x, y, points );\n};\n\nmath.joinLines = function(lineSet) {\n\n  var vertices = new Array(lineSet.length / 2);\n\n  var currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY;\n  var nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY;\n\n  for (var i = 0; i < lineSet.length / 4; i++) {\n    currentLineStartX = lineSet[i * 4];\n    currentLineStartY = lineSet[i * 4 + 1];\n    currentLineEndX = lineSet[i * 4 + 2];\n    currentLineEndY = lineSet[i * 4 + 3];\n\n    if (i < lineSet.length / 4 - 1) {\n      nextLineStartX = lineSet[(i + 1) * 4];\n      nextLineStartY = lineSet[(i + 1) * 4 + 1];\n      nextLineEndX = lineSet[(i + 1) * 4 + 2];\n      nextLineEndY = lineSet[(i + 1) * 4 + 3];\n    } else {\n      nextLineStartX = lineSet[0];\n      nextLineStartY = lineSet[1];\n      nextLineEndX = lineSet[2];\n      nextLineEndY = lineSet[3];\n    }\n\n    var intersection = this.finiteLinesIntersect(\n      currentLineStartX, currentLineStartY,\n      currentLineEndX, currentLineEndY,\n      nextLineStartX, nextLineStartY,\n      nextLineEndX, nextLineEndY,\n      true);\n\n    vertices[i * 2] = intersection[0];\n    vertices[i * 2 + 1] = intersection[1];\n  }\n\n  return vertices;\n};\n\nmath.expandPolygon = function(points, pad) {\n\n  var expandedLineSet = new Array(points.length * 2);\n\n  var currentPointX, currentPointY, nextPointX, nextPointY;\n\n  for (var i = 0; i < points.length / 2; i++) {\n    currentPointX = points[i * 2];\n    currentPointY = points[i * 2 + 1];\n\n    if (i < points.length / 2 - 1) {\n      nextPointX = points[(i + 1) * 2];\n      nextPointY = points[(i + 1) * 2 + 1];\n    } else {\n      nextPointX = points[0];\n      nextPointY = points[1];\n    }\n\n    // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY]\n\n    // Assume CCW polygon winding\n\n    var offsetX = (nextPointY - currentPointY);\n    var offsetY = -(nextPointX - currentPointX);\n\n    // Normalize\n    var offsetLength = Math.sqrt(offsetX * offsetX + offsetY * offsetY);\n    var normalizedOffsetX = offsetX / offsetLength;\n    var normalizedOffsetY = offsetY / offsetLength;\n\n    expandedLineSet[i * 4] = currentPointX + normalizedOffsetX * pad;\n    expandedLineSet[i * 4 + 1] = currentPointY + normalizedOffsetY * pad;\n    expandedLineSet[i * 4 + 2] = nextPointX + normalizedOffsetX * pad;\n    expandedLineSet[i * 4 + 3] = nextPointY + normalizedOffsetY * pad;\n  }\n\n  return expandedLineSet;\n};\n\nmath.intersectLineEllipse = function(\n  x, y, centerX, centerY, ellipseWradius, ellipseHradius) {\n\n  var dispX = centerX - x;\n  var dispY = centerY - y;\n\n  dispX /= ellipseWradius;\n  dispY /= ellipseHradius;\n\n  var len = Math.sqrt(dispX * dispX + dispY * dispY);\n\n  var newLength = len - 1;\n\n  if (newLength < 0) {\n    return [];\n  }\n\n  var lenProportion = newLength / len;\n\n  return [(centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y];\n};\n\n// Returns intersections of increasing distance from line's start point\nmath.intersectLineCircle = function(\n  x1, y1, x2, y2, centerX, centerY, radius) {\n\n  // Calculate d, direction vector of line\n  var d = [x2 - x1, y2 - y1]; // Direction vector of line\n  var c = [centerX, centerY]; // Center of circle\n  var f = [x1 - centerX, y1 - centerY];\n\n  var a = d[0] * d[0] + d[1] * d[1];\n  var b = 2 * (f[0] * d[0] + f[1] * d[1]);\n  var c = (f[0] * f[0] + f[1] * f[1]) - radius * radius ;\n\n  var discriminant = b*b-4*a*c;\n\n  if (discriminant < 0) {\n    return [];\n  }\n\n  var t1 = (-b + Math.sqrt(discriminant)) / (2 * a);\n  var t2 = (-b - Math.sqrt(discriminant)) / (2 * a);\n\n  var tMin = Math.min(t1, t2);\n  var tMax = Math.max(t1, t2);\n  var inRangeParams = [];\n\n  if (tMin >= 0 && tMin <= 1) {\n    inRangeParams.push(tMin);\n  }\n\n  if (tMax >= 0 && tMax <= 1) {\n    inRangeParams.push(tMax);\n  }\n\n  if (inRangeParams.length === 0) {\n    return [];\n  }\n\n  var nearIntersectionX = inRangeParams[0] * d[0] + x1;\n  var nearIntersectionY = inRangeParams[0] * d[1] + y1;\n\n  if (inRangeParams.length > 1) {\n\n    if (inRangeParams[0] == inRangeParams[1]) {\n      return [nearIntersectionX, nearIntersectionY];\n    } else {\n\n      var farIntersectionX = inRangeParams[1] * d[0] + x1;\n      var farIntersectionY = inRangeParams[1] * d[1] + y1;\n\n      return [nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY];\n    }\n\n  } else {\n    return [nearIntersectionX, nearIntersectionY];\n  }\n\n};\n\nmath.findCircleNearPoint = function(centerX, centerY,\n  radius, farX, farY) {\n\n  var displacementX = farX - centerX;\n  var displacementY = farY - centerY;\n  var distance = Math.sqrt(displacementX * displacementX\n    + displacementY * displacementY);\n\n  var unitDisplacementX = displacementX / distance;\n  var unitDisplacementY = displacementY / distance;\n\n  return [centerX + unitDisplacementX * radius,\n    centerY + unitDisplacementY * radius];\n};\n\nmath.findMaxSqDistanceToOrigin = function(points) {\n  var maxSqDistance = 0.000001;\n  var sqDistance;\n\n  for (var i = 0; i < points.length / 2; i++) {\n\n    sqDistance = points[i * 2] * points[i * 2]\n      + points[i * 2 + 1] * points[i * 2 + 1];\n\n    if (sqDistance > maxSqDistance) {\n      maxSqDistance = sqDistance;\n    }\n  }\n\n  return maxSqDistance;\n};\n\nmath.finiteLinesIntersect = function(\n  x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines) {\n\n  var ua_t = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);\n  var ub_t = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);\n  var u_b = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);\n\n  if (u_b !== 0) {\n    var ua = ua_t / u_b;\n    var ub = ub_t / u_b;\n\n    if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n      return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];\n\n    } else {\n      if (!infiniteLines) {\n        return [];\n      } else {\n        return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];\n      }\n    }\n  } else {\n    if (ua_t === 0 || ub_t === 0) {\n\n      // Parallel, coincident lines. Check if overlap\n\n      // Check endpoint of second line\n      if ([x1, x2, x4].sort()[1] === x4) {\n        return [x4, y4];\n      }\n\n      // Check start point of second line\n      if ([x1, x2, x3].sort()[1] === x3) {\n        return [x3, y3];\n      }\n\n      // Endpoint of first line\n      if ([x3, x4, x2].sort()[1] === x2) {\n        return [x2, y2];\n      }\n\n      return [];\n    } else {\n\n      // Parallel, non-coincident\n      return [];\n    }\n  }\n};\n\nmath.polygonIntersectLine = function(\n  x, y, basePoints, centerX, centerY, width, height, padding) {\n\n  var intersections = [];\n  var intersection;\n\n  var transformedPoints = new Array(basePoints.length);\n\n  for (var i = 0; i < transformedPoints.length / 2; i++) {\n    transformedPoints[i * 2] = basePoints[i * 2] * width + centerX;\n    transformedPoints[i * 2 + 1] = basePoints[i * 2 + 1] * height + centerY;\n  }\n\n  var points;\n\n  if (padding > 0) {\n    var expandedLineSet = math.expandPolygon(\n      transformedPoints,\n      -padding);\n\n    points = math.joinLines(expandedLineSet);\n  } else {\n    points = transformedPoints;\n  }\n  // var points = transformedPoints;\n\n  var currentX, currentY, nextX, nextY;\n\n  for (var i = 0; i < points.length / 2; i++) {\n\n    currentX = points[i * 2];\n    currentY = points[i * 2 + 1];\n\n    if (i < points.length / 2 - 1) {\n      nextX = points[(i + 1) * 2];\n      nextY = points[(i + 1) * 2 + 1];\n    } else {\n      nextX = points[0];\n      nextY = points[1];\n    }\n\n    intersection = this.finiteLinesIntersect(\n      x, y, centerX, centerY,\n      currentX, currentY,\n      nextX, nextY);\n\n    if (intersection.length !== 0) {\n      intersections.push(intersection[0], intersection[1]);\n    }\n  }\n\n  return intersections;\n};\n\nmath.shortenIntersection = function(\n  intersection, offset, amount) {\n\n  var disp = [intersection[0] - offset[0], intersection[1] - offset[1]];\n\n  var length = Math.sqrt(disp[0] * disp[0] + disp[1] * disp[1]);\n\n  var lenRatio = (length - amount) / length;\n\n  if (lenRatio < 0) {\n    lenRatio = 0.00001;\n  }\n\n  return [offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1]];\n};\n\nmath.generateUnitNgonPointsFitToSquare = function(sides, rotationRadians) {\n  var points = math.generateUnitNgonPoints(sides, rotationRadians);\n  points = math.fitPolygonToSquare(points);\n\n  return points;\n};\n\nmath.fitPolygonToSquare = function(points){\n  var x, y;\n  var sides = points.length/2;\n  var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n\n  for (var i = 0; i < sides; i++) {\n    x = points[2 * i];\n    y = points[2 * i + 1];\n\n    minX = Math.min( minX, x );\n    maxX = Math.max( maxX, x );\n    minY = Math.min( minY, y );\n    maxY = Math.max( maxY, y );\n  }\n\n  // stretch factors\n  var sx = 2 / (maxX - minX);\n  var sy = 2 / (maxY - minY);\n\n  for (var i = 0; i < sides; i++){\n    x = points[2 * i] = points[2 * i] * sx;\n    y = points[2 * i + 1] = points[2 * i + 1] * sy;\n\n    minX = Math.min( minX, x );\n    maxX = Math.max( maxX, x );\n    minY = Math.min( minY, y );\n    maxY = Math.max( maxY, y );\n  }\n\n  if( minY < -1 ){\n    for (var i = 0; i < sides; i++){\n      y = points[2 * i + 1] = points[2 * i + 1] + (-1 -minY);\n    }\n  }\n\n  return points;\n};\n\nmath.generateUnitNgonPoints = function(sides, rotationRadians) {\n\n  var increment = 1.0 / sides * 2 * Math.PI;\n  var startAngle = sides % 2 === 0 ?\n    Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0;\n    //    console.log(nodeShapes['square']);\n  startAngle += rotationRadians;\n\n  var points = new Array(sides * 2);\n\n  var currentAngle, x, y;\n  for (var i = 0; i < sides; i++) {\n    currentAngle = i * increment + startAngle;\n\n    x = points[2 * i] = Math.cos(currentAngle);// * (1 + i/2);\n    y = points[2 * i + 1] = Math.sin(-currentAngle);//  * (1 + i/2);\n  }\n\n  return points;\n};\n\nmath.getRoundRectangleRadius = function(width, height) {\n\n  // Set the default radius, unless half of width or height is smaller than default\n  return Math.min(width / 4, height / 4, 8);\n};\n\nmodule.exports = math;\n\n},{}],80:[function(_dereq_,module,exports){\n// internal, minimal Promise impl s.t. apis can return promises in old envs\n// based on thenable (http://github.com/rse/thenable)\n\n'use strict';\n\n/*  promise states [Promises/A+ 2.1]  */\nvar STATE_PENDING   = 0;                                         /*  [Promises/A+ 2.1.1]  */\nvar STATE_FULFILLED = 1;                                         /*  [Promises/A+ 2.1.2]  */\nvar STATE_REJECTED  = 2;                                         /*  [Promises/A+ 2.1.3]  */\n\n/*  promise object constructor  */\nvar api = function (executor) {\n  /*  optionally support non-constructor/plain-function call  */\n  if (!(this instanceof api))\n    return new api(executor);\n\n  /*  initialize object  */\n  this.id           = \"Thenable/1.0.7\";\n  this.state        = STATE_PENDING; /*  initial state  */\n  this.fulfillValue = undefined;     /*  initial value  */     /*  [Promises/A+ 1.3, 2.1.2.2]  */\n  this.rejectReason = undefined;     /*  initial reason */     /*  [Promises/A+ 1.5, 2.1.3.2]  */\n  this.onFulfilled  = [];            /*  initial handlers  */\n  this.onRejected   = [];            /*  initial handlers  */\n\n  /*  provide optional information-hiding proxy  */\n  this.proxy = {\n    then: this.then.bind(this)\n  };\n\n  /*  support optional executor function  */\n  if (typeof executor === \"function\")\n    executor.call(this, this.fulfill.bind(this), this.reject.bind(this));\n};\n\n/*  promise API methods  */\napi.prototype = {\n  /*  promise resolving methods  */\n  fulfill: function (value) { return deliver(this, STATE_FULFILLED, \"fulfillValue\", value); },\n  reject:  function (value) { return deliver(this, STATE_REJECTED,  \"rejectReason\", value); },\n\n  /*  \"The then Method\" [Promises/A+ 1.1, 1.2, 2.2]  */\n  then: function (onFulfilled, onRejected) {\n    var curr = this;\n    var next = new api();                                    /*  [Promises/A+ 2.2.7]  */\n    curr.onFulfilled.push(\n      resolver(onFulfilled, next, \"fulfill\"));             /*  [Promises/A+ 2.2.2/2.2.6]  */\n    curr.onRejected.push(\n      resolver(onRejected,  next, \"reject\" ));             /*  [Promises/A+ 2.2.3/2.2.6]  */\n    execute(curr);\n    return next.proxy;                                       /*  [Promises/A+ 2.2.7, 3.3]  */\n  }\n};\n\n/*  deliver an action  */\nvar deliver = function (curr, state, name, value) {\n  if (curr.state === STATE_PENDING) {\n    curr.state = state;                                      /*  [Promises/A+ 2.1.2.1, 2.1.3.1]  */\n    curr[name] = value;                                      /*  [Promises/A+ 2.1.2.2, 2.1.3.2]  */\n    execute(curr);\n  }\n  return curr;\n};\n\n/*  execute all handlers  */\nvar execute = function (curr) {\n  if (curr.state === STATE_FULFILLED)\n    execute_handlers(curr, \"onFulfilled\", curr.fulfillValue);\n  else if (curr.state === STATE_REJECTED)\n    execute_handlers(curr, \"onRejected\",  curr.rejectReason);\n};\n\n/*  execute particular set of handlers  */\nvar execute_handlers = function (curr, name, value) {\n  /* global setImmediate: true */\n  /* global setTimeout: true */\n\n  /*  short-circuit processing  */\n  if (curr[name].length === 0)\n    return;\n\n  /*  iterate over all handlers, exactly once  */\n  var handlers = curr[name];\n  curr[name] = [];                                             /*  [Promises/A+ 2.2.2.3, 2.2.3.3]  */\n  var func = function () {\n    for (var i = 0; i < handlers.length; i++)\n      handlers[i](value);                                  /*  [Promises/A+ 2.2.5]  */\n  };\n\n  /*  execute procedure asynchronously  */                     /*  [Promises/A+ 2.2.4, 3.1]  */\n  if (typeof setImmediate === \"function\")\n    setImmediate(func);\n  else\n    setTimeout(func, 0);\n};\n\n/*  generate a resolver function  */\nvar resolver = function (cb, next, method) {\n  return function (value) {\n    if (typeof cb !== \"function\")                            /*  [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4]  */\n      next[method].call(next, value);                      /*  [Promises/A+ 2.2.7.3, 2.2.7.4]  */\n    else {\n      var result;\n      try { result = cb(value); }                          /*  [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2]  */\n      catch (e) {\n        next.reject(e);                                  /*  [Promises/A+ 2.2.7.2]  */\n        return;\n      }\n      resolve(next, result);                               /*  [Promises/A+ 2.2.7.1]  */\n    }\n  };\n};\n\n/*  \"Promise Resolution Procedure\"  */                           /*  [Promises/A+ 2.3]  */\nvar resolve = function (promise, x) {\n  /*  sanity check arguments  */                               /*  [Promises/A+ 2.3.1]  */\n  if (promise === x || promise.proxy === x) {\n    promise.reject(new TypeError(\"cannot resolve promise with itself\"));\n    return;\n  }\n\n  /*  surgically check for a \"then\" method\n    (mainly to just call the \"getter\" of \"then\" only once)  */\n  var then;\n  if ((typeof x === \"object\" && x !== null) || typeof x === \"function\") {\n    try { then = x.then; }                                   /*  [Promises/A+ 2.3.3.1, 3.5]  */\n    catch (e) {\n      promise.reject(e);                                   /*  [Promises/A+ 2.3.3.2]  */\n      return;\n    }\n  }\n\n  /*  handle own Thenables    [Promises/A+ 2.3.2]\n    and similar \"thenables\" [Promises/A+ 2.3.3]  */\n  if (typeof then === \"function\") {\n    var resolved = false;\n    try {\n      /*  call retrieved \"then\" method */                  /*  [Promises/A+ 2.3.3.3]  */\n      then.call(x,\n        /*  resolvePromise  */                           /*  [Promises/A+ 2.3.3.3.1]  */\n        function (y) {\n          if (resolved) return; resolved = true;       /*  [Promises/A+ 2.3.3.3.3]  */\n          if (y === x)                                 /*  [Promises/A+ 3.6]  */\n            promise.reject(new TypeError(\"circular thenable chain\"));\n          else\n            resolve(promise, y);\n        },\n\n        /*  rejectPromise  */                            /*  [Promises/A+ 2.3.3.3.2]  */\n        function (r) {\n          if (resolved) return; resolved = true;       /*  [Promises/A+ 2.3.3.3.3]  */\n          promise.reject(r);\n        }\n      );\n    }\n    catch (e) {\n      if (!resolved)                                       /*  [Promises/A+ 2.3.3.3.3]  */\n        promise.reject(e);                               /*  [Promises/A+ 2.3.3.3.4]  */\n    }\n    return;\n  }\n\n  /*  handle other values  */\n  promise.fulfill(x);                                          /*  [Promises/A+ 2.3.4, 2.3.3.4]  */\n};\n\n// use native promises where possible\nvar Promise = typeof Promise === 'undefined' ? api : Promise;\n\n// so we always have Promise.all()\nPromise.all = Promise.all || function( ps ){\n  return new Promise(function( resolveAll, rejectAll ){\n    var vals = new Array( ps.length );\n    var doneCount = 0;\n\n    var fulfill = function( i, val ){\n      vals[i] = val;\n      doneCount++;\n\n      if( doneCount === ps.length ){\n        resolveAll( vals );\n      }\n    };\n\n    for( var i = 0; i < ps.length; i++ ){\n      (function( i ){\n        var p = ps[i];\n        var isPromise = p.then != null;\n\n        if( isPromise ){\n          p.then(function( val ){\n            fulfill( i, val );\n          }, function( err ){\n            rejectAll( err );\n          });\n        } else {\n          var val = p;\n          fulfill( i, val );\n        }\n      })( i );\n    }\n\n  });\n};\n\nmodule.exports = Promise;\n\n},{}],81:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('./is');\nvar util = _dereq_('./util');\n\nvar Selector = function( onlyThisGroup, selector ){\n\n  if( !(this instanceof Selector) ){\n    return new Selector(onlyThisGroup, selector);\n  }\n\n  if( selector === undefined && onlyThisGroup !== undefined ){\n    selector = onlyThisGroup;\n    onlyThisGroup = undefined;\n  }\n\n  var self = this;\n\n  self._private = {\n    selectorText: null,\n    invalid: true\n  };\n\n  if( !selector || ( is.string(selector) && selector.match(/^\\s*$/) ) ){\n\n    if( onlyThisGroup == null ){\n      // ignore\n      self.length = 0;\n    } else {\n      self[0] = newQuery();\n      self[0].group = onlyThisGroup;\n      self.length = 1;\n    }\n\n  } else if( is.elementOrCollection( selector ) ){\n    var collection = selector.collection();\n\n    self[0] = newQuery();\n    self[0].collection = collection;\n    self.length = 1;\n\n  } else if( is.fn( selector ) ) {\n    self[0] = newQuery();\n    self[0].filter = selector;\n    self.length = 1;\n\n  } else if( is.string( selector ) ){\n\n    // the current subject in the query\n    var currentSubject = null;\n\n    // storage for parsed queries\n    var newQuery = function(){\n      return {\n        classes: [],\n        colonSelectors: [],\n        data: [],\n        group: null,\n        ids: [],\n        meta: [],\n\n        // fake selectors\n        collection: null, // a collection to match against\n        filter: null, // filter function\n\n        // these are defined in the upward direction rather than down (e.g. child)\n        // because we need to go up in Selector.filter()\n        parent: null, // parent query obj\n        ancestor: null, // ancestor query obj\n        subject: null, // defines subject in compound query (subject query obj; points to self if subject)\n\n        // use these only when subject has been defined\n        child: null,\n        descendant: null\n      };\n    };\n\n    // tokens in the query language\n    var tokens = {\n      metaChar: '[\\\\!\\\\\"\\\\#\\\\$\\\\%\\\\&\\\\\\'\\\\(\\\\)\\\\*\\\\+\\\\,\\\\.\\\\/\\\\:\\\\;\\\\<\\\\=\\\\>\\\\?\\\\@\\\\[\\\\]\\\\^\\\\`\\\\{\\\\|\\\\}\\\\~]', // chars we need to escape in var names, etc\n      comparatorOp: '=|\\\\!=|>|>=|<|<=|\\\\$=|\\\\^=|\\\\*=', // binary comparison op (used in data selectors)\n      boolOp: '\\\\?|\\\\!|\\\\^', // boolean (unary) operators (used in data selectors)\n      string: '\"(?:\\\\\\\\\"|[^\"])+\"' + '|' + \"'(?:\\\\\\\\'|[^'])+'\", // string literals (used in data selectors) -- doublequotes | singlequotes\n      number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123\n      meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection)\n      separator: '\\\\s*,\\\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass\n      descendant: '\\\\s+',\n      child: '\\\\s+>\\\\s+',\n      subject: '\\\\$'\n    };\n    tokens.variable = '(?:[\\\\w-]|(?:\\\\\\\\'+ tokens.metaChar +'))+'; // a variable name\n    tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number\n    tokens.className = tokens.variable; // a class name (follows variable conventions)\n    tokens.id = tokens.variable; // an element id (follows variable conventions)\n\n    // when a token like a variable has escaped meta characters, we need to clean the backslashes out\n    // so that values get compared properly in Selector.filter()\n    var cleanMetaChars = function(str){\n      return str.replace(new RegExp('\\\\\\\\(' + tokens.metaChar + ')', 'g'), function(match, $1, offset, original){\n        return $1;\n      });\n    };\n\n    // add @ variants to comparatorOp\n    var ops = tokens.comparatorOp.split('|');\n    for( var i = 0; i < ops.length; i++ ){\n      var op = ops[i];\n      tokens.comparatorOp += '|@' + op;\n    }\n\n    // add ! variants to comparatorOp\n    var ops = tokens.comparatorOp.split('|');\n    for( var i = 0; i < ops.length; i++ ){\n      var op = ops[i];\n\n      if( op.indexOf('!') >= 0 ){ continue; } // skip ops that explicitly contain !\n      if( op === '=' ){ continue; } // skip = b/c != is explicitly defined\n\n      tokens.comparatorOp += '|\\\\!' + op;\n    }\n\n    // NOTE: add new expression syntax here to have it recognised by the parser;\n    // - a query contains all adjacent (i.e. no separator in between) expressions;\n    // - the current query is stored in self[i] --- you can use the reference to `this` in the populate function;\n    // - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward\n    // - when you add something here, also add to Selector.toString()\n    var exprs = [\n      {\n        name: 'group',\n        query: true,\n        regex: '(node|edge|\\\\*)',\n        populate: function( group ){\n          this.group = group == \"*\" ? group : group + 's';\n        }\n      },\n\n      {\n        name: 'state',\n        query: true,\n        // NB: if one colon selector is a substring of another from its start, place the longer one first\n        // e.g. :foobar|:foo\n        regex: '(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)',\n        populate: function( state ){\n          this.colonSelectors.push( state );\n        }\n      },\n\n      {\n        name: 'id',\n        query: true,\n        regex: '\\\\#('+ tokens.id +')',\n        populate: function( id ){\n          this.ids.push( cleanMetaChars(id) );\n        }\n      },\n\n      {\n        name: 'className',\n        query: true,\n        regex: '\\\\.('+ tokens.className +')',\n        populate: function( className ){\n          this.classes.push( cleanMetaChars(className) );\n        }\n      },\n\n      {\n        name: 'dataExists',\n        query: true,\n        regex: '\\\\[\\\\s*('+ tokens.variable +')\\\\s*\\\\]',\n        populate: function( variable ){\n          this.data.push({\n            field: cleanMetaChars(variable)\n          });\n        }\n      },\n\n      {\n        name: 'dataCompare',\n        query: true,\n        regex: '\\\\[\\\\s*('+ tokens.variable +')\\\\s*('+ tokens.comparatorOp +')\\\\s*('+ tokens.value +')\\\\s*\\\\]',\n        populate: function( variable, comparatorOp, value ){\n          var valueIsString = new RegExp('^' + tokens.string + '$').exec(value) != null;\n\n          if( valueIsString ){\n            value = value.substring(1, value.length - 1);\n          } else {\n            value = parseFloat(value);\n          }\n\n          this.data.push({\n            field: cleanMetaChars(variable),\n            operator: comparatorOp,\n            value: value\n          });\n        }\n      },\n\n      {\n        name: 'dataBool',\n        query: true,\n        regex: '\\\\[\\\\s*('+ tokens.boolOp +')\\\\s*('+ tokens.variable +')\\\\s*\\\\]',\n        populate: function( boolOp, variable ){\n          this.data.push({\n            field: cleanMetaChars(variable),\n            operator: boolOp\n          });\n        }\n      },\n\n      {\n        name: 'metaCompare',\n        query: true,\n        regex: '\\\\[\\\\[\\\\s*('+ tokens.meta +')\\\\s*('+ tokens.comparatorOp +')\\\\s*('+ tokens.number +')\\\\s*\\\\]\\\\]',\n        populate: function( meta, comparatorOp, number ){\n          this.meta.push({\n            field: cleanMetaChars(meta),\n            operator: comparatorOp,\n            value: parseFloat(number)\n          });\n        }\n      },\n\n      {\n        name: 'nextQuery',\n        separator: true,\n        regex: tokens.separator,\n        populate: function(){\n          // go on to next query\n          self[++i] = newQuery();\n          currentSubject = null;\n        }\n      },\n\n      {\n        name: 'child',\n        separator: true,\n        regex: tokens.child,\n        populate: function(){\n          // this query is the parent of the following query\n          var childQuery = newQuery();\n          childQuery.parent = this;\n          childQuery.subject = currentSubject;\n\n          // we're now populating the child query with expressions that follow\n          self[i] = childQuery;\n        }\n      },\n\n      {\n        name: 'descendant',\n        separator: true,\n        regex: tokens.descendant,\n        populate: function(){\n          // this query is the ancestor of the following query\n          var descendantQuery = newQuery();\n          descendantQuery.ancestor = this;\n          descendantQuery.subject = currentSubject;\n\n          // we're now populating the descendant query with expressions that follow\n          self[i] = descendantQuery;\n        }\n      },\n\n      {\n        name: 'subject',\n        modifier: true,\n        regex: tokens.subject,\n        populate: function(){\n          if( currentSubject != null && this.subject != this ){\n            util.error('Redefinition of subject in selector `' + selector + '`');\n            return false;\n          }\n\n          currentSubject = this;\n          this.subject = this;\n        }\n\n      }\n    ];\n\n    self._private.selectorText = selector;\n    var remaining = selector;\n    var i = 0;\n\n    // of all the expressions, find the first match in the remaining text\n    var consumeExpr = function( expectation ){\n      var expr;\n      var match;\n      var name;\n\n      for( var j = 0; j < exprs.length; j++ ){\n        var e = exprs[j];\n        var n = e.name;\n\n        // ignore this expression if it doesn't meet the expectation function\n        if( is.fn( expectation ) && !expectation(n, e) ){ continue; }\n\n        var m = remaining.match(new RegExp( '^' + e.regex ));\n\n        if( m != null ){\n          match = m;\n          expr = e;\n          name = n;\n\n          var consumed = m[0];\n          remaining = remaining.substring( consumed.length );\n\n          break; // we've consumed one expr, so we can return now\n        }\n      }\n\n      return {\n        expr: expr,\n        match: match,\n        name: name\n      };\n    };\n\n    // consume all leading whitespace\n    var consumeWhitespace = function(){\n      var match = remaining.match(/^\\s+/);\n\n      if( match ){\n        var consumed = match[0];\n        remaining = remaining.substring( consumed.length );\n      }\n    };\n\n    self[0] = newQuery(); // get started\n\n    consumeWhitespace(); // get rid of leading whitespace\n    for(;;){\n      var check = consumeExpr();\n\n      if( check.expr == null ){\n        util.error('The selector `'+ selector +'`is invalid');\n        return;\n      } else {\n        var args = [];\n        for(var j = 1; j < check.match.length; j++){\n          args.push( check.match[j] );\n        }\n\n        // let the token populate the selector object (i.e. in self[i])\n        var ret = check.expr.populate.apply( self[i], args );\n\n        if( ret === false ){ return; } // exit if population failed\n      }\n\n      // we're done when there's nothing left to parse\n      if( remaining.match(/^\\s*$/) ){\n        break;\n      }\n    }\n\n    self.length = i + 1;\n\n    // adjust references for subject\n    for(var j = 0; j < self.length; j++){\n      var query = self[j];\n\n      if( query.subject != null ){\n        // go up the tree until we reach the subject\n        for(;;){\n          if( query.subject == query ){ break; } // done if subject is self\n\n          if( query.parent != null ){ // swap parent/child reference\n            var parent = query.parent;\n            var child = query;\n\n            child.parent = null;\n            parent.child = child;\n\n            query = parent; // go up the tree\n          } else if( query.ancestor != null ){ // swap ancestor/descendant\n            var ancestor = query.ancestor;\n            var descendant = query;\n\n            descendant.ancestor = null;\n            ancestor.descendant = descendant;\n\n            query = ancestor; // go up the tree\n          } else {\n            util.error('When adjusting references for the selector `'+ query +'`, neither parent nor ancestor was found');\n            break;\n          }\n        } // for\n\n        self[j] = query.subject; // subject should be the root query\n      } // if\n    } // for\n\n    // make sure for each query that the subject group matches the implicit group if any\n    if( onlyThisGroup != null ){\n      for(var j = 0; j < self.length; j++){\n        if( self[j].group != null && self[j].group != onlyThisGroup ){\n          util.error('Group `'+ self[j].group +'` conflicts with implicit group `'+ onlyThisGroup +'` in selector `'+ selector +'`');\n          return;\n        }\n\n        self[j].group = onlyThisGroup; // set to implicit group\n      }\n    }\n\n  } else {\n    util.error('A selector must be created from a string; found ' + selector);\n    return;\n  }\n\n  self._private.invalid = false;\n\n};\n\nvar selfn = Selector.prototype;\n\nselfn.size = function(){\n  return this.length;\n};\n\nselfn.eq = function(i){\n  return this[i];\n};\n\nvar queryMatches = function(query, element){\n  // check group\n  if( query.group != null && query.group != '*' && query.group != element._private.group ){\n    return false;\n  }\n\n  var cy = element.cy();\n\n  // check colon selectors\n  var allColonSelectorsMatch = true;\n  for(var k = 0; k < query.colonSelectors.length; k++){\n    var sel = query.colonSelectors[k];\n\n    switch(sel){\n    case ':selected':\n      allColonSelectorsMatch = element.selected();\n      break;\n    case ':unselected':\n      allColonSelectorsMatch = !element.selected();\n      break;\n    case ':selectable':\n      allColonSelectorsMatch = element.selectable();\n      break;\n    case ':unselectable':\n      allColonSelectorsMatch = !element.selectable();\n      break;\n    case ':locked':\n      allColonSelectorsMatch = element.locked();\n      break;\n    case ':unlocked':\n      allColonSelectorsMatch = !element.locked();\n      break;\n    case ':visible':\n      allColonSelectorsMatch = element.visible();\n      break;\n    case ':hidden':\n      allColonSelectorsMatch = !element.visible();\n      break;\n    case ':transparent':\n      allColonSelectorsMatch = element.transparent();\n      break;\n    case ':grabbed':\n      allColonSelectorsMatch = element.grabbed();\n      break;\n    case ':free':\n      allColonSelectorsMatch = !element.grabbed();\n      break;\n    case ':removed':\n      allColonSelectorsMatch = element.removed();\n      break;\n    case ':inside':\n      allColonSelectorsMatch = !element.removed();\n      break;\n    case ':grabbable':\n      allColonSelectorsMatch = element.grabbable();\n      break;\n    case ':ungrabbable':\n      allColonSelectorsMatch = !element.grabbable();\n      break;\n    case ':animated':\n      allColonSelectorsMatch = element.animated();\n      break;\n    case ':unanimated':\n      allColonSelectorsMatch = !element.animated();\n      break;\n    case ':parent':\n      allColonSelectorsMatch = element.isNode() && element.children().nonempty();\n      break;\n    case ':child':\n    case ':nonorphan':\n      allColonSelectorsMatch = element.isNode() && element.parent().nonempty();\n      break;\n    case ':orphan':\n      allColonSelectorsMatch = element.isNode() && element.parent().empty();\n      break;\n    case ':loop':\n      allColonSelectorsMatch = element.isEdge() && element.data('source') === element.data('target');\n      break;\n    case ':simple':\n      allColonSelectorsMatch = element.isEdge() && element.data('source') !== element.data('target');\n      break;\n    case ':active':\n      allColonSelectorsMatch = element.active();\n      break;\n    case ':inactive':\n      allColonSelectorsMatch = !element.active();\n      break;\n    case ':touch':\n      allColonSelectorsMatch = is.touch();\n      break;\n    case ':backgrounding':\n      allColonSelectorsMatch = element.backgrounding();\n      break;\n    case ':nonbackgrounding':\n      allColonSelectorsMatch = !element.backgrounding();\n      break;\n    }\n\n    if( !allColonSelectorsMatch ) break;\n  }\n  if( !allColonSelectorsMatch ) return false;\n\n  // check id\n  var allIdsMatch = true;\n  for(var k = 0; k < query.ids.length; k++){\n    var id = query.ids[k];\n    var actualId = element._private.data.id;\n\n    allIdsMatch = allIdsMatch && (id == actualId);\n\n    if( !allIdsMatch ) break;\n  }\n  if( !allIdsMatch ) return false;\n\n  // check classes\n  var allClassesMatch = true;\n  for(var k = 0; k < query.classes.length; k++){\n    var cls = query.classes[k];\n\n    allClassesMatch = allClassesMatch && element.hasClass(cls);\n\n    if( !allClassesMatch ) break;\n  }\n  if( !allClassesMatch ) return false;\n\n  // generic checking for data/metadata\n  var operandsMatch = function(params){\n    var allDataMatches = true;\n    for(var k = 0; k < query[params.name].length; k++){\n      var data = query[params.name][k];\n      var operator = data.operator;\n      var value = data.value;\n      var field = data.field;\n      var matches;\n\n      if( operator != null && value != null ){\n\n        var fieldVal = params.fieldValue(field);\n        var fieldStr = !is.string(fieldVal) && !is.number(fieldVal) ? '' : '' + fieldVal;\n        var valStr = '' + value;\n\n        var caseInsensitive = false;\n        if( operator.indexOf('@') >= 0 ){\n          fieldStr = fieldStr.toLowerCase();\n          valStr = valStr.toLowerCase();\n\n          operator = operator.replace('@', '');\n          caseInsensitive = true;\n        }\n\n        var notExpr = false;\n        var handledNotExpr = false;\n        if( operator.indexOf('!') >= 0 ){\n          operator = operator.replace('!', '');\n          notExpr = true;\n        }\n\n        // if we're doing a case insensitive comparison, then we're using a STRING comparison\n        // even if we're comparing numbers\n        if( caseInsensitive ){\n          value = valStr.toLowerCase();\n          fieldVal = fieldStr.toLowerCase();\n        }\n\n        switch(operator){\n        case '*=':\n          matches = fieldStr.search(valStr) >= 0;\n          break;\n        case '$=':\n          matches = new RegExp(valStr + '$').exec(fieldStr) != null;\n          break;\n        case '^=':\n          matches = new RegExp('^' + valStr).exec(fieldStr) != null;\n          break;\n        case '=':\n          matches = fieldVal === value;\n          break;\n        case '!=':\n          matches = fieldVal !== value;\n          break;\n        case '>':\n          matches = !notExpr ? fieldVal > value : fieldVal <= value;\n          handledNotExpr = true;\n          break;\n        case '>=':\n          matches = !notExpr ? fieldVal >= value : fieldVal < value;\n          handledNotExpr = true;\n          break;\n        case '<':\n          matches = !notExpr ? fieldVal < value : fieldVal >= value;\n          handledNotExpr = true;\n          break;\n        case '<=':\n          matches = !notExpr ? fieldVal <= value : fieldVal > value;\n          handledNotExpr = true;\n          break;\n        default:\n          matches = false;\n          break;\n\n        }\n      } else if( operator != null ){\n        switch(operator){\n        case '?':\n          matches = params.fieldTruthy(field);\n          break;\n        case '!':\n          matches = !params.fieldTruthy(field);\n          break;\n        case '^':\n          matches = params.fieldUndefined(field);\n          break;\n        }\n      } else {\n        matches = !params.fieldUndefined(field);\n      }\n\n      if( notExpr && !handledNotExpr ){\n        matches = !matches;\n        handledNotExpr = true;\n      }\n\n      if( !matches ){\n        allDataMatches = false;\n        break;\n      }\n    } // for\n\n    return allDataMatches;\n  }; // operandsMatch\n\n  // check data matches\n  var allDataMatches = operandsMatch({\n    name: 'data',\n    fieldValue: function(field){\n      return element._private.data[field];\n    },\n    fieldRef: function(field){\n      return 'element._private.data.' + field;\n    },\n    fieldUndefined: function(field){\n      return element._private.data[field] === undefined;\n    },\n    fieldTruthy: function(field){\n      if( element._private.data[field] ){\n        return true;\n      }\n      return false;\n    }\n  });\n\n  if( !allDataMatches ){\n    return false;\n  }\n\n  // check metadata matches\n  var allMetaMatches = operandsMatch({\n    name: 'meta',\n    fieldValue: function(field){\n      return element[field]();\n    },\n    fieldRef: function(field){\n      return 'element.' + field + '()';\n    },\n    fieldUndefined: function(field){\n      return element[field]() == null;\n    },\n    fieldTruthy: function(field){\n      if( element[field]() ){\n        return true;\n      }\n      return false;\n    }\n  });\n\n  if( !allMetaMatches ){\n    return false;\n  }\n\n  // check collection\n  if( query.collection != null ){\n    var matchesAny = query.collection._private.ids[ element.id() ] != null;\n\n    if( !matchesAny ){\n      return false;\n    }\n  }\n\n  // check filter function\n  if( query.filter != null && element.collection().filter( query.filter ).size() === 0 ){\n    return false;\n  }\n\n\n  // check parent/child relations\n  var confirmRelations = function( query, elements ){\n    if( query != null ){\n      var matches = false;\n\n      if( !cy.hasCompoundNodes() ){\n        return false;\n      }\n\n      elements = elements(); // make elements functional so we save cycles if query == null\n\n      // query must match for at least one element (may be recursive)\n      for(var i = 0; i < elements.length; i++){\n        if( queryMatches( query, elements[i] ) ){\n          matches = true;\n          break;\n        }\n      }\n\n      return matches;\n    } else {\n      return true;\n    }\n  };\n\n  if (! confirmRelations(query.parent, function(){\n    return element.parent();\n  }) ){ return false; }\n\n  if (! confirmRelations(query.ancestor, function(){\n    return element.parents();\n  }) ){ return false; }\n\n  if (! confirmRelations(query.child, function(){\n    return element.children();\n  }) ){ return false; }\n\n  if (! confirmRelations(query.descendant, function(){\n    return element.descendants();\n  }) ){ return false; }\n\n  // we've reached the end, so we've matched everything for this query\n  return true;\n}; // queryMatches\n\n// filter an existing collection\nselfn.filter = function(collection){\n  var self = this;\n  var cy = collection.cy();\n\n  // don't bother trying if it's invalid\n  if( self._private.invalid ){\n    return cy.collection();\n  }\n\n  var selectorFunction = function(i, element){\n    for(var j = 0; j < self.length; j++){\n      var query = self[j];\n\n      if( queryMatches(query, element) ){\n        return true;\n      }\n    }\n\n    return false;\n  };\n\n  if( self._private.selectorText == null ){\n    selectorFunction = function(){ return true; };\n  }\n\n  var filteredCollection = collection.filter( selectorFunction );\n\n  return filteredCollection;\n}; // filter\n\n// does selector match a single element?\nselfn.matches = function(ele){\n  var self = this;\n\n  // don't bother trying if it's invalid\n  if( self._private.invalid ){\n    return false;\n  }\n\n  for(var j = 0; j < self.length; j++){\n    var query = self[j];\n\n    if( queryMatches(query, ele) ){\n      return true;\n    }\n  }\n\n  return false;\n}; // filter\n\n// ith query to string\nselfn.toString = selfn.selector = function(){\n\n  var str = '';\n\n  var clean = function(obj, isValue){\n    if( is.string(obj) ){\n      return isValue ? '\"' + obj + '\"' : obj;\n    }\n    return '';\n  };\n\n  var queryToString = function(query){\n    var str = '';\n\n    if( query.subject === query ){\n      str += '$';\n    }\n\n    var group = clean(query.group);\n    str += group.substring(0, group.length - 1);\n\n    for(var j = 0; j < query.data.length; j++){\n      var data = query.data[j];\n\n      if( data.value ){\n        str += '[' + data.field + clean(data.operator) + clean(data.value, true) + ']';\n      } else {\n        str += '[' + clean(data.operator) + data.field + ']';\n      }\n    }\n\n    for(var j = 0; j < query.meta.length; j++){\n      var meta = query.meta[j];\n      str += '[[' + meta.field + clean(meta.operator) + clean(meta.value, true) + ']]';\n    }\n\n    for(var j = 0; j < query.colonSelectors.length; j++){\n      var sel = query.colonSelectors[i];\n      str += sel;\n    }\n\n    for(var j = 0; j < query.ids.length; j++){\n      var sel = '#' + query.ids[i];\n      str += sel;\n    }\n\n    for(var j = 0; j < query.classes.length; j++){\n      var sel = '.' + query.classes[j];\n      str += sel;\n    }\n\n    if( query.parent != null ){\n      str = queryToString( query.parent ) + ' > ' + str;\n    }\n\n    if( query.ancestor != null ){\n      str = queryToString( query.ancestor ) + ' ' + str;\n    }\n\n    if( query.child != null ){\n      str += ' > ' + queryToString( query.child );\n    }\n\n    if( query.descendant != null ){\n      str += ' ' + queryToString( query.descendant );\n    }\n\n    return str;\n  };\n\n  for(var i = 0; i < this.length; i++){\n    var query = this[i];\n\n    str += queryToString( query );\n\n    if( this.length > 1 && i < this.length - 1 ){\n      str += ', ';\n    }\n  }\n\n  return str;\n};\n\nmodule.exports = Selector;\n\n},{\"./is\":77,\"./util\":94}],82:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\nvar styfn = {};\n\n// (potentially expensive calculation)\n// apply the style to the element based on\n// - its bypass\n// - what selectors match it\nstyfn.apply = function( eles ){\n  var self = this;\n\n  if( self._private.newStyle ){ // clear style caches\n    this._private.contextStyles = {};\n    this._private.propDiffs = {};\n  }\n\n  for( var ie = 0; ie < eles.length; ie++ ){\n    var ele = eles[ie];\n    var cxtMeta = self.getContextMeta( ele );\n    var cxtStyle = self.getContextStyle( cxtMeta );\n    var app = self.applyContextStyle( cxtMeta, cxtStyle, ele );\n\n    self.updateTransitions( ele, app.diffProps );\n    self.updateStyleHints( ele );\n\n  } // for elements\n\n  self._private.newStyle = false;\n};\n\nstyfn.getPropertiesDiff = function( oldCxtKey, newCxtKey ){\n  var self = this;\n  var cache = self._private.propDiffs = self._private.propDiffs || {};\n  var dualCxtKey = oldCxtKey + '-' + newCxtKey;\n  var cachedVal = cache[dualCxtKey];\n\n  if( cachedVal ){\n    return cachedVal;\n  }\n\n  var diffProps = [];\n  var addedProp = {};\n\n  for( var i = 0; i < self.length; i++ ){\n    var cxt = self[i];\n    var oldHasCxt = oldCxtKey[i] === 't';\n    var newHasCxt = newCxtKey[i] === 't';\n    var cxtHasDiffed = oldHasCxt !== newHasCxt;\n    var cxtHasMappedProps = cxt.mappedProperties.length > 0;\n\n    if( cxtHasDiffed || cxtHasMappedProps ){\n      var props;\n\n      if( cxtHasDiffed && cxtHasMappedProps ){\n        props = cxt.properties; // suffices b/c mappedProperties is a subset of properties\n      } else if( cxtHasDiffed ){\n        props = cxt.properties; // need to check them all\n      } else if( cxtHasMappedProps ){\n        props = cxt.mappedProperties; // only need to check mapped\n      }\n\n      for( var j = 0; j < props.length; j++ ){\n        var prop = props[j];\n        var name = prop.name;\n\n        // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter\n        // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result\n        // is cached)\n        var laterCxtOverrides = false;\n        for( var k = i + 1; k < self.length; k++ ){\n          var laterCxt = self[k];\n          var hasLaterCxt = newCxtKey[k] === 't';\n\n          if( !hasLaterCxt ){ continue; } // can't override unless the context is active\n\n          laterCxtOverrides = laterCxt.properties[ prop.name ] != null;\n\n          if( laterCxtOverrides ){ break; } // exit early as long as one later context overrides\n        }\n\n        if( !addedProp[name] && !laterCxtOverrides ){\n          addedProp[name] = true;\n          diffProps.push( name );\n        }\n      } // for props\n    } // if\n\n  } // for contexts\n\n  cache[ dualCxtKey ] = diffProps;\n  return diffProps;\n};\n\nstyfn.getContextMeta = function( ele ){\n  var self = this;\n  var cxtKey = '';\n  var diffProps;\n  var prevKey = ele._private.styleCxtKey || '';\n\n  if( self._private.newStyle ){\n    prevKey = ''; // since we need to apply all style if a fresh stylesheet\n  }\n\n  // get the cxt key\n  for( var i = 0; i < self.length; i++ ){\n    var context = self[i];\n    var contextSelectorMatches = context.selector && context.selector.matches( ele ); // NB: context.selector may be null for 'core'\n\n    if( contextSelectorMatches ){\n      cxtKey += 't';\n    } else {\n      cxtKey += 'f';\n    }\n  } // for context\n\n  diffProps = self.getPropertiesDiff( prevKey, cxtKey );\n\n  ele._private.styleCxtKey = cxtKey;\n\n  return {\n    key: cxtKey,\n    diffPropNames: diffProps\n  };\n};\n\n// gets a computed ele style object based on matched contexts\nstyfn.getContextStyle = function( cxtMeta ){\n  var cxtKey = cxtMeta.key;\n  var self = this;\n  var cxtStyles = this._private.contextStyles = this._private.contextStyles || {};\n\n  // if already computed style, returned cached copy\n  if( cxtStyles[cxtKey] ){ return cxtStyles[cxtKey]; }\n\n  var style = {\n    _private: {\n      key: cxtKey\n    }\n  };\n\n  for( var i = 0; i < self.length; i++ ){\n    var cxt = self[i];\n    var hasCxt = cxtKey[i] === 't';\n\n    if( !hasCxt ){ continue; }\n\n    for( var j = 0; j < cxt.properties.length; j++ ){\n      var prop = cxt.properties[j];\n      var styProp = style[ prop.name ] = prop;\n\n      styProp.context = cxt;\n    }\n  }\n\n  cxtStyles[cxtKey] = style;\n  return style;\n};\n\nstyfn.applyContextStyle = function( cxtMeta, cxtStyle, ele ){\n  var self = this;\n  var diffProps = cxtMeta.diffPropNames;\n  var retDiffProps = {};\n\n  for( var i = 0; i < diffProps.length; i++ ){\n    var diffPropName = diffProps[i];\n    var cxtProp = cxtStyle[ diffPropName ];\n    var eleProp = ele._private.style[ diffPropName ];\n\n    // save cycles when the context prop doesn't need to be applied\n    if( !cxtProp || eleProp === cxtProp ){ continue; }\n\n    var retDiffProp = retDiffProps[ diffPropName ] = {\n      prev: eleProp\n    };\n\n    self.applyParsedProperty( ele, cxtProp );\n\n    retDiffProp.next = ele._private.style[ diffPropName ];\n\n    if( retDiffProp.next && retDiffProp.next.bypass ){\n      retDiffProp.next = retDiffProp.next.bypassed;\n    }\n  }\n\n  return {\n    diffProps: retDiffProps\n  };\n};\n\nstyfn.updateStyleHints = function(ele){\n  var _p = ele._private;\n  var self = this;\n  var style = _p.style;\n\n  if( ele.removed() ){ return; }\n\n  // set whether has pie or not; for greater efficiency\n  var hasPie = false;\n  if( _p.group === 'nodes' && self._private.hasPie ){\n    for( var i = 1; i <= self.pieBackgroundN; i++ ){ // 1..N\n      var size = _p.style['pie-' + i + '-background-size'].value;\n\n      if( size > 0 ){\n        hasPie = true;\n        break;\n      }\n    }\n  }\n\n  _p.hasPie = hasPie;\n\n  var transform = style['text-transform'].strValue;\n  var content = style['label'].strValue;\n  var fStyle = style['font-style'].strValue;\n  var size = style['font-size'].pfValue + 'px';\n  var family = style['font-family'].strValue;\n  // var variant = style['font-variant'].strValue;\n  var weight = style['font-weight'].strValue;\n  var valign = style['text-valign'].strValue;\n  var halign = style['text-valign'].strValue;\n  var oWidth = style['text-outline-width'].pfValue;\n  var wrap = style['text-wrap'].strValue;\n  var wrapW = style['text-max-width'].pfValue;\n  _p.labelKey = fStyle +'$'+ size +'$'+ family +'$'+ weight +'$'+ content +'$'+ transform +'$'+ valign +'$'+ halign +'$'+ oWidth + '$' + wrap + '$' + wrapW;\n  _p.fontKey = fStyle +'$'+ weight +'$'+ size +'$'+ family;\n\n  var width = style['width'].pfValue;\n  var height = style['height'].pfValue;\n  var borderW = style['border-width'].pfValue;\n  _p.boundingBoxKey = width +'$'+ height +'$'+ borderW;\n\n  if( ele._private.group === 'edges' ){\n    var cpss = style['control-point-step-size'].pfValue;\n    var cpd = style['control-point-distances'] ? style['control-point-distances'].pfValue.join('_') : undefined;\n    var cpw = style['control-point-weights'].value.join('_');\n    var curve = style['curve-style'].strValue;\n    var sd = style['segment-distances'] ? style['segment-distances'].pfValue.join('_') : undefined;\n    var sw = style['segment-weights'].value.join('_');\n\n    _p.boundingBoxKey += '$'+ cpss +'$'+ cpd +'$'+ cpw +'$'+ sd +'$'+ sw +'$'+ curve;\n  }\n\n  _p.styleKey = Date.now();\n};\n\n// apply a property to the style (for internal use)\n// returns whether application was successful\n//\n// now, this function flattens the property, and here's how:\n//\n// for parsedProp:{ bypass: true, deleteBypass: true }\n// no property is generated, instead the bypass property in the\n// element's style is replaced by what's pointed to by the `bypassed`\n// field in the bypass property (i.e. restoring the property the\n// bypass was overriding)\n//\n// for parsedProp:{ mapped: truthy }\n// the generated flattenedProp:{ mapping: prop }\n//\n// for parsedProp:{ bypass: true }\n// the generated flattenedProp:{ bypassed: parsedProp }\nstyfn.applyParsedProperty = function( ele, parsedProp ){\n  var self = this;\n  var prop = parsedProp;\n  var style = ele._private.style;\n  var fieldVal, flatProp;\n  var types = self.types;\n  var type = self.properties[ prop.name ].type;\n  var propIsBypass = prop.bypass;\n  var origProp = style[ prop.name ];\n  var origPropIsBypass = origProp && origProp.bypass;\n  var _p = ele._private;\n\n  // can't apply auto to width or height unless it's a parent node\n  if( (parsedProp.name === 'height' || parsedProp.name === 'width') && ele.isNode() ){\n    if( parsedProp.value === 'auto' && !ele.isParent() ){\n      return false;\n    } else if( parsedProp.value !== 'auto' && ele.isParent() ){\n      prop = parsedProp = this.parse( parsedProp.name, 'auto', propIsBypass );\n    }\n  }\n\n  // check if we need to delete the current bypass\n  if( propIsBypass && prop.deleteBypass ){ // then this property is just here to indicate we need to delete\n    var currentProp = style[ prop.name ];\n\n    // can only delete if the current prop is a bypass and it points to the property it was overriding\n    if( !currentProp ){\n      return true; // property is already not defined\n    } else if( currentProp.bypass && currentProp.bypassed ){ // then replace the bypass property with the original\n\n      // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary)\n      style[ prop.name ] = currentProp.bypassed;\n      return true;\n\n    } else {\n      return false; // we're unsuccessful deleting the bypass\n    }\n  }\n\n  var printMappingErr = function(){\n    util.error('Do not assign mappings to elements without corresponding data (e.g. ele `'+ ele.id() +'` for property `'+ prop.name +'` with data field `'+ prop.field +'`); try a `['+ prop.field +']` selector to limit scope to elements with `'+ prop.field +'` defined');\n  };\n\n  // put the property in the style objects\n  switch( prop.mapped ){ // flatten the property if mapped\n  case types.mapData:\n  case types.mapLayoutData:\n  case types.mapScratch:\n\n    var isLayout = prop.mapped === types.mapLayoutData;\n    var isScratch = prop.mapped === types.mapScratch;\n\n    // flatten the field (e.g. data.foo.bar)\n    var fields = prop.field.split(\".\");\n    var fieldVal;\n\n    if( isScratch || isLayout ){\n      fieldVal = _p.scratch;\n    } else {\n      fieldVal = _p.data;\n    }\n\n    for( var i = 0; i < fields.length && fieldVal; i++ ){\n      var field = fields[i];\n      fieldVal = fieldVal[ field ];\n    }\n\n    var percent;\n    if( !is.number(fieldVal) ){ // then keep the mapping but assume 0% for now\n      percent = 0;\n    } else {\n      percent = (fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin);\n    }\n\n    // make sure to bound percent value\n    if( percent < 0 ){\n      percent = 0;\n    } else if( percent > 1 ){\n      percent = 1;\n    }\n\n    if( type.color ){\n      var r1 = prop.valueMin[0];\n      var r2 = prop.valueMax[0];\n      var g1 = prop.valueMin[1];\n      var g2 = prop.valueMax[1];\n      var b1 = prop.valueMin[2];\n      var b2 = prop.valueMax[2];\n      var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3];\n      var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3];\n\n      var clr = [\n        Math.round( r1 + (r2 - r1)*percent ),\n        Math.round( g1 + (g2 - g1)*percent ),\n        Math.round( b1 + (b2 - b1)*percent ),\n        Math.round( a1 + (a2 - a1)*percent )\n      ];\n\n      flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing\n        bypass: prop.bypass, // we're a bypass if the mapping property is a bypass\n        name: prop.name,\n        value: clr,\n        strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')'\n      };\n\n    } else if( type.number ){\n      var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent;\n      flatProp = this.parse( prop.name, calcValue, prop.bypass, true );\n\n    } else {\n      return false; // can only map to colours and numbers\n    }\n\n    if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself\n      flatProp = this.parse( prop.name, origProp.strValue, prop.bypass, true );\n    }\n\n    if( !flatProp ){ printMappingErr(); }\n    flatProp.mapping = prop; // keep a reference to the mapping\n    prop = flatProp; // the flattened (mapped) property is the one we want\n\n    break;\n\n  // direct mapping\n  case types.data:\n  case types.layoutData:\n  case types.scratch:\n    var isLayout = prop.mapped === types.layoutData;\n    var isScratch = prop.mapped === types.scratch;\n\n    // flatten the field (e.g. data.foo.bar)\n    var fields = prop.field.split(\".\");\n    var fieldVal;\n\n    if( isScratch || isLayout ){\n      fieldVal = _p.scratch;\n    } else {\n      fieldVal = _p.data;\n    }\n\n    if( fieldVal ){ for( var i = 0; i < fields.length; i++ ){\n      var field = fields[i];\n      fieldVal = fieldVal[ field ];\n    } }\n\n    flatProp = this.parse( prop.name, fieldVal, prop.bypass, true );\n\n    if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself\n      var flatPropVal = origProp ? origProp.strValue : '';\n\n      flatProp = this.parse( prop.name, flatPropVal, prop.bypass, true );\n    }\n\n    if( !flatProp ){ printMappingErr(); }\n    flatProp.mapping = prop; // keep a reference to the mapping\n    prop = flatProp; // the flattened (mapped) property is the one we want\n\n    break;\n\n  case types.fn:\n    var fn = prop.value;\n    var fnRetVal = fn( ele );\n\n    flatProp = this.parse( prop.name, fnRetVal, prop.bypass, true );\n    flatProp.mapping = prop; // keep a reference to the mapping\n    prop = flatProp; // the flattened (mapped) property is the one we want\n\n    break;\n\n  case undefined:\n    break; // just set the property\n\n  default:\n    return false; // not a valid mapping\n  }\n\n  // if the property is a bypass property, then link the resultant property to the original one\n  if( propIsBypass ){\n    if( origPropIsBypass ){ // then this bypass overrides the existing one\n      prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass\n    } else { // then link the orig prop to the new bypass\n      prop.bypassed = origProp;\n    }\n\n    style[ prop.name ] = prop; // and set\n\n  } else { // prop is not bypass\n    if( origPropIsBypass ){ // then keep the orig prop (since it's a bypass) and link to the new prop\n      origProp.bypassed = prop;\n    } else { // then just replace the old prop with the new one\n      style[ prop.name ] = prop;\n    }\n  }\n\n  return true;\n};\n\n// updates the visual style for all elements (useful for manual style modification after init)\nstyfn.update = function(){\n  var cy = this._private.cy;\n  var eles = cy.elements();\n\n  eles.updateStyle();\n};\n\n// just update the functional properties (i.e. mappings) in the elements'\n// styles (less expensive than recalculation)\nstyfn.updateMappers = function( eles ){\n  var self = this;\n\n  for( var i = 0; i < eles.length; i++ ){ // for each ele\n    var ele = eles[i];\n    var style = ele._private.style;\n\n    for( var j = 0; j < self.properties.length; j++ ){ // for each prop\n      var prop = self.properties[j];\n      var propInStyle = style[ prop.name ];\n\n      if( propInStyle && propInStyle.mapping ){\n        var mapping = propInStyle.mapping;\n        this.applyParsedProperty( ele, mapping ); // reapply the mapping property\n      }\n    }\n\n    this.updateStyleHints( ele );\n  }\n};\n\n// diffProps : { name => { prev, next } }\nstyfn.updateTransitions = function( ele, diffProps, isBypass ){\n  var self = this;\n  var _p = ele._private;\n  var style = _p.style;\n  var props = style['transition-property'].value;\n  var duration = style['transition-duration'].pfValue;\n  var delay = style['transition-delay'].pfValue;\n  var css = {};\n\n  if( props.length > 0 && duration > 0 ){\n\n    // build up the style to animate towards\n    var anyPrev = false;\n    for( var i = 0; i < props.length; i++ ){\n      var prop = props[i];\n      var styProp = style[ prop ];\n      var diffProp = diffProps[ prop ];\n\n      if( !diffProp ){ continue; }\n\n      var prevProp = diffProp.prev;\n      var fromProp = prevProp;\n      var toProp = diffProp.next != null ? diffProp.next : styProp;\n      var diff = false;\n      var initVal;\n      var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity)\n\n      if( !fromProp ){ continue; }\n\n      // consider px values\n      if( is.number( fromProp.pfValue ) && is.number( toProp.pfValue ) ){\n        diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy\n        initVal = fromProp.pfValue + initDt * diff;\n\n      // consider numerical values\n      } else if( is.number( fromProp.value ) && is.number( toProp.value ) ){\n        diff = toProp.value - fromProp.value; // nonzero is truthy\n        initVal = fromProp.value + initDt * diff;\n\n      // consider colour values\n      } else if( is.array( fromProp.value ) && is.array( toProp.value ) ){\n        diff = fromProp.value[0] !== toProp.value[0]\n          || fromProp.value[1] !== toProp.value[1]\n          || fromProp.value[2] !== toProp.value[2]\n        ;\n\n        initVal = fromProp.strValue;\n      }\n\n      // the previous value is good for an animation only if it's different\n      if( diff ){\n        css[ prop ] = toProp.strValue; // to val\n        this.applyBypass( ele, prop, initVal ); // from val\n        anyPrev = true;\n      }\n\n    } // end if props allow ani\n\n    // can't transition if there's nothing previous to transition from\n    if( !anyPrev ){ return; }\n\n    _p.transitioning = true;\n\n    ele.stop();\n\n    if( delay > 0 ){\n      ele.delay( delay );\n    }\n\n    ele.animate({\n      css: css\n    }, {\n      duration: duration,\n      easing: style['transition-timing-function'].value,\n      queue: false,\n      complete: function(){\n        if( !isBypass ){\n          self.removeBypasses( ele, props );\n        }\n\n        _p.transitioning = false;\n      }\n    });\n\n  } else if( _p.transitioning ){\n    ele.stop();\n\n    this.removeBypasses( ele, props );\n\n    _p.transitioning = false;\n  }\n};\n\nmodule.exports = styfn;\n\n},{\"../is\":77,\"../util\":94}],83:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar util = _dereq_('../util');\n\nvar styfn = {};\n\n// bypasses are applied to an existing style on an element, and just tacked on temporarily\n// returns true iff application was successful for at least 1 specified property\nstyfn.applyBypass = function( eles, name, value, updateTransitions ){\n  var self = this;\n  var props = [];\n  var isBypass = true;\n\n  // put all the properties (can specify one or many) in an array after parsing them\n  if( name === \"*\" || name === \"**\" ){ // apply to all property names\n\n    if( value !== undefined ){\n      for( var i = 0; i < self.properties.length; i++ ){\n        var prop = self.properties[i];\n        var name = prop.name;\n\n        var parsedProp = this.parse(name, value, true);\n\n        if( parsedProp ){\n          props.push( parsedProp );\n        }\n      }\n    }\n\n  } else if( is.string(name) ){ // then parse the single property\n    var parsedProp = this.parse(name, value, true);\n\n    if( parsedProp ){\n      props.push( parsedProp );\n    }\n  } else if( is.plainObject(name) ){ // then parse each property\n    var specifiedProps = name;\n    updateTransitions = value;\n\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var name = prop.name;\n      var value = specifiedProps[ name ];\n\n      if( value === undefined ){ // try camel case name too\n        value = specifiedProps[ util.dash2camel(name) ];\n      }\n\n      if( value !== undefined ){\n        var parsedProp = this.parse(name, value, true);\n\n        if( parsedProp ){\n          props.push( parsedProp );\n        }\n      }\n    }\n  } else { // can't do anything without well defined properties\n    return false;\n  }\n\n  // we've failed if there are no valid properties\n  if( props.length === 0 ){ return false; }\n\n  // now, apply the bypass properties on the elements\n  var ret = false; // return true if at least one succesful bypass applied\n  for( var i = 0; i < eles.length; i++ ){ // for each ele\n    var ele = eles[i];\n    var style = ele._private.style;\n    var diffProps = {};\n    var diffProp;\n\n    for( var j = 0; j < props.length; j++ ){ // for each prop\n      var prop = props[j];\n\n      if( updateTransitions ){\n        var prevProp = style[ prop.name ];\n        diffProp = diffProps[ prop.name ] = { prev: prevProp };\n      }\n\n      ret = this.applyParsedProperty( ele, prop ) || ret;\n\n      if( updateTransitions ){\n        diffProp.next = style[ prop.name ];\n      }\n\n    } // for props\n\n    if( ret ){\n      this.updateStyleHints( ele );\n    }\n\n    if( updateTransitions ){\n      this.updateTransitions( ele, diffProps, isBypass );\n    }\n  } // for eles\n\n  return ret;\n};\n\n// only useful in specific cases like animation\nstyfn.overrideBypass = function( eles, name, value ){\n  name = util.camel2dash(name);\n\n  for( var i = 0; i < eles.length; i++ ){\n    var ele = eles[i];\n    var prop = ele._private.style[ name ];\n    var type = this.properties[ name ].type;\n    var isColor = type.color;\n    var isMulti = type.mutiple;\n\n    if( !prop.bypass ){ // need a bypass if one doesn't exist\n      this.applyBypass( ele, name, value );\n      continue;\n    }\n\n    prop.value = value;\n\n    if( prop.pfValue != null ){\n      prop.pfValue = value;\n    }\n\n    if( isColor ){\n      prop.strValue = 'rgb(' + value.join(',') + ')';\n    } else if( isMulti ){\n      prop.strValue = value.join(' ');\n    } else {\n      prop.strValue = '' + value;\n    }\n  }\n};\n\nstyfn.removeAllBypasses = function( eles, updateTransitions ){\n  return this.removeBypasses( eles, this.propertyNames, updateTransitions );\n};\n\nstyfn.removeBypasses = function( eles, props, updateTransitions ){\n  var isBypass = true;\n\n  for( var j = 0; j < eles.length; j++ ){\n    var ele = eles[j];\n    var diffProps = {};\n    var style = ele._private.style;\n\n    for( var i = 0; i < props.length; i++ ){\n      var name = props[i];\n      var prop = this.properties[ name ];\n      var value = ''; // empty => remove bypass\n      var parsedProp = this.parse(name, value, true);\n      var prevProp = style[ prop.name ];\n      var diffProp = diffProps[ prop.name ] = { prev: prevProp };\n\n      this.applyParsedProperty(ele, parsedProp);\n\n      diffProp.next = style[ prop.name ];\n    } // for props\n\n    this.updateStyleHints( ele );\n\n    if( updateTransitions ){\n      this.updateTransitions( ele, diffProps, isBypass );\n    }\n  } // for eles\n};\n\nmodule.exports = styfn;\n\n},{\"../is\":77,\"../util\":94}],84:[function(_dereq_,module,exports){\n'use strict';\n\nvar window = _dereq_('../window');\n\nvar styfn = {};\n\n// gets what an em size corresponds to in pixels relative to a dom element\nstyfn.getEmSizeInPixels = function(){\n  var px = this.containerCss('font-size');\n\n  if( px != null ){\n    return parseFloat( px );\n  } else {\n    return 1; // for headless\n  }\n};\n\n// gets css property from the core container\nstyfn.containerCss = function( propName ){\n  var cy = this._private.cy;\n  var domElement = cy.container();\n\n  if( window && domElement && window.getComputedStyle ){\n    return window.getComputedStyle(domElement).getPropertyValue( propName );\n  }\n};\n\nmodule.exports = styfn;\n\n},{\"../window\":100}],85:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\nvar styfn = {};\n\n// gets the rendered style for an element\nstyfn.getRenderedStyle = function( ele ){\n  return this.getRawStyle( ele, true );\n};\n\n// gets the raw style for an element\nstyfn.getRawStyle = function( ele, isRenderedVal ){\n  var self = this;\n  var ele = ele[0]; // insure it's an element\n\n  if( ele ){\n    var rstyle = {};\n\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var val = self.getStylePropertyValue( ele, prop.name, isRenderedVal );\n\n      if( val ){\n        rstyle[ prop.name ] = val;\n        rstyle[ util.dash2camel(prop.name) ] = val;\n      }\n    }\n\n    return rstyle;\n  }\n};\n\nstyfn.getStylePropertyValue = function( ele, propName, isRenderedVal ){\n  var self = this;\n  var ele = ele[0]; // insure it's an element\n\n  if( ele ){\n    var style = ele._private.style;\n    var prop = self.properties[ propName ];\n    var type = prop.type;\n    var styleProp = style[ prop.name ];\n    var zoom = ele.cy().zoom();\n\n    if( styleProp ){\n      var units = styleProp.units ? type.implicitUnits || 'px' : null;\n      var val = units ? [].concat( styleProp.pfValue ).map(function( pfValue ){\n        return ( pfValue * (isRenderedVal ? zoom : 1) ) + units;\n      }).join(' ') : styleProp.strValue;\n\n      return val;\n    }\n  }\n};\n\n// gets the value style for an element (useful for things like animations)\nstyfn.getValueStyle = function( ele ){\n  var self = this;\n  var rstyle = {};\n  var style;\n  var isEle = is.element(ele);\n\n  if( isEle ){\n    style = ele._private.style;\n  } else {\n    style = ele; // just passed the style itself\n  }\n\n  if( style ){\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var styleProp = style[ prop.name ] || style[ util.dash2camel(prop.name) ];\n\n      if( styleProp !== undefined ){ // then make a prop of it\n        if( is.plainObject( styleProp ) ){\n          styleProp = this.parse( prop.name, styleProp.strValue );\n        } else {\n          styleProp = this.parse( prop.name, styleProp );\n        }\n      }\n\n      if( styleProp ){\n        rstyle[ prop.name ] = styleProp;\n        rstyle[ util.dash2camel(prop.name) ] = styleProp;\n      }\n    }\n  }\n\n  return rstyle;\n};\n\nstyfn.getPropsList = function( propsObj ){\n  var self = this;\n  var rstyle = [];\n  var style = propsObj;\n  var props = self.properties;\n\n  if( style ){\n    for( var name in style ){\n      var val = style[name];\n      var prop = props[name] || props[ util.camel2dash(name) ];\n      var styleProp = this.parse( prop.name, val );\n\n      rstyle.push( styleProp );\n    }\n  }\n\n  return rstyle;\n};\n\nmodule.exports = styfn;\n\n},{\"../is\":77,\"../util\":94}],86:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar util = _dereq_('../util');\nvar Selector = _dereq_('../selector');\n\nvar Style = function( cy ){\n\n  if( !(this instanceof Style) ){\n    return new Style(cy);\n  }\n\n  if( !is.core(cy) ){\n    util.error('A style must have a core reference');\n    return;\n  }\n\n  this._private = {\n    cy: cy,\n    coreStyle: {},\n    newStyle: true\n  };\n\n  this.length = 0;\n\n  this.addDefaultStylesheet();\n};\n\nvar styfn = Style.prototype;\n\nstyfn.instanceString = function(){\n  return 'style';\n};\n\n// remove all contexts\nstyfn.clear = function(){\n  for( var i = 0; i < this.length; i++ ){\n    this[i] = undefined;\n  }\n  this.length = 0;\n  this._private.newStyle = true;\n\n  return this; // chaining\n};\n\nstyfn.resetToDefault = function(){\n  this.clear();\n  this.addDefaultStylesheet();\n\n  return this;\n};\n\n// builds a style object for the 'core' selector\nstyfn.core = function(){\n  return this._private.coreStyle;\n};\n\n// create a new context from the specified selector string and switch to that context\nstyfn.selector = function( selectorStr ){\n  // 'core' is a special case and does not need a selector\n  var selector = selectorStr === 'core' ? null : new Selector( selectorStr );\n\n  var i = this.length++; // new context means new index\n  this[i] = {\n    selector: selector,\n    properties: [],\n    mappedProperties: [],\n    index: i\n  };\n\n  return this; // chaining\n};\n\n// add one or many css rules to the current context\nstyfn.css = function(){\n  var self = this;\n  var args = arguments;\n\n  switch( args.length ){\n  case 1:\n    var map = args[0];\n\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var mapVal = map[ prop.name ];\n\n      if( mapVal === undefined ){\n        mapVal = map[ util.dash2camel(prop.name) ];\n      }\n\n      if( mapVal !== undefined ){\n        this.cssRule( prop.name, mapVal );\n      }\n    }\n\n    break;\n\n  case 2:\n    this.cssRule( args[0], args[1] );\n    break;\n\n  default:\n    break; // do nothing if args are invalid\n  }\n\n  return this; // chaining\n};\nstyfn.style = styfn.css;\n\n// add a single css rule to the current context\nstyfn.cssRule = function( name, value ){\n  // name-value pair\n  var property = this.parse( name, value );\n\n  // add property to current context if valid\n  if( property ){\n    var i = this.length - 1;\n    this[i].properties.push( property );\n    this[i].properties[ property.name ] = property; // allow access by name as well\n\n    if( property.name.match(/pie-(\\d+)-background-size/) && property.value ){\n      this._private.hasPie = true;\n    }\n\n    if( property.mapped ){\n      this[i].mappedProperties.push( property );\n    }\n\n    // add to core style if necessary\n    var currentSelectorIsCore = !this[i].selector;\n    if( currentSelectorIsCore ){\n      this._private.coreStyle[ property.name ] = property;\n    }\n  }\n\n  return this; // chaining\n};\n\n// static function\nStyle.fromJson = function( cy, json ){\n  var style = new Style( cy );\n\n  style.fromJson( json );\n\n  return style;\n};\n\nStyle.fromString = function( cy, string ){\n  return new Style( cy ).fromString( string );\n};\n\n[\n  _dereq_('./apply'),\n  _dereq_('./bypass'),\n  _dereq_('./container'),\n  _dereq_('./get-for-ele'),\n  _dereq_('./json'),\n  _dereq_('./string-sheet'),\n  _dereq_('./properties'),\n  _dereq_('./parse')\n].forEach(function( props ){\n  util.extend( styfn, props );\n});\n\n\nStyle.types = styfn.types;\nStyle.properties = styfn.properties;\n\nmodule.exports = Style;\n\n},{\"../is\":77,\"../selector\":81,\"../util\":94,\"./apply\":82,\"./bypass\":83,\"./container\":84,\"./get-for-ele\":85,\"./json\":87,\"./parse\":88,\"./properties\":89,\"./string-sheet\":90}],87:[function(_dereq_,module,exports){\n'use strict';\n\nvar styfn = {};\n\nstyfn.applyFromJson = function( json ){\n  var style = this;\n\n  for( var i = 0; i < json.length; i++ ){\n    var context = json[i];\n    var selector = context.selector;\n    var props = context.style || context.css;\n\n    style.selector( selector ); // apply selector\n\n    for( var name in props ){\n      var value = props[name];\n\n      style.css( name, value ); // apply property\n    }\n  }\n\n  return style;\n};\n\n// accessible cy.style() function\nstyfn.fromJson = function( json ){\n  var style = this;\n\n  style.resetToDefault();\n  style.applyFromJson( json );\n\n  return style;\n};\n\n// get json from cy.style() api\nstyfn.json = function(){\n  var json = [];\n\n  for( var i = this.defaultLength; i < this.length; i++ ){\n    var cxt = this[i];\n    var selector = cxt.selector;\n    var props = cxt.properties;\n    var css = {};\n\n    for( var j = 0; j < props.length; j++ ){\n      var prop = props[j];\n      css[ prop.name ] = prop.strValue;\n    }\n\n    json.push({\n      selector: !selector ? 'core' : selector.toString(),\n      style: css\n    });\n  }\n\n  return json;\n};\n\nmodule.exports = styfn;\n\n},{}],88:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar is = _dereq_('../is');\n\nvar styfn = {};\n\n// a caching layer for property parsing\nstyfn.parse = function( name, value, propIsBypass, propIsFlat ){\n  var argHash = [ name, value, propIsBypass, propIsFlat ].join('$');\n  var propCache = this.propCache = this.propCache || {};\n  var ret;\n  var impl = parseImpl.bind( this );\n\n  if( !(ret = propCache[argHash]) ){\n    ret = propCache[argHash] = impl( name, value, propIsBypass, propIsFlat );\n  }\n\n  // always need a copy since props are mutated later in their lifecycles\n  ret = util.copy( ret );\n\n  if( ret ){\n    ret.value = util.copy( ret.value ); // because it could be an array, e.g. colour\n  }\n\n  return ret;\n};\n\n// parse a property; return null on invalid; return parsed property otherwise\n// fields :\n// - name : the name of the property\n// - value : the parsed, native-typed value of the property\n// - strValue : a string value that represents the property value in valid css\n// - bypass : true iff the property is a bypass property\nvar parseImpl = function( name, value, propIsBypass, propIsFlat ){\n  var self = this;\n\n  name = util.camel2dash( name ); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName')\n\n  var property = self.properties[ name ];\n  var passedValue = value;\n  var types = self.types;\n\n  if( !property ){ return null; } // return null on property of unknown name\n  if( value === undefined || value === null ){ return null; } // can't assign null\n\n  // the property may be an alias\n  if( property.alias ){\n    property = property.pointsTo;\n    name = property.name;\n  }\n\n  var valueIsString = is.string(value);\n  if( valueIsString ){ // trim the value to make parsing easier\n    value = value.trim();\n  }\n\n  var type = property.type;\n  if( !type ){ return null; } // no type, no luck\n\n  // check if bypass is null or empty string (i.e. indication to delete bypass property)\n  if( propIsBypass && (value === '' || value === null) ){\n    return {\n      name: name,\n      value: value,\n      bypass: true,\n      deleteBypass: true\n    };\n  }\n\n  // check if value is a function used as a mapper\n  if( is.fn(value) ){\n    return {\n      name: name,\n      value: value,\n      strValue: 'fn',\n      mapped: types.fn,\n      bypass: propIsBypass\n    };\n  }\n\n  // check if value is mapped\n  var data, mapData, layoutData, mapLayoutData, scratch, mapScratch;\n  if( !valueIsString || propIsFlat ){\n    // then don't bother to do the expensive regex checks\n\n  } else if(\n    ( data = new RegExp( types.data.regex ).exec( value ) ) ||\n    ( layoutData = new RegExp( types.layoutData.regex ).exec( value ) ) ||\n    ( scratch = new RegExp( types.scratch.regex ).exec( value ) )\n  ){\n    if( propIsBypass ){ return false; } // mappers not allowed in bypass\n\n    var mapped;\n    if( data ){\n      mapped = types.data;\n    } else if( layoutData ){\n      mapped = types.layoutData;\n    } else {\n      mapped = types.scratch;\n    }\n\n    data = data || layoutData || scratch;\n\n    return {\n      name: name,\n      value: data,\n      strValue: '' + value,\n      mapped: mapped,\n      field: data[1],\n      bypass: propIsBypass\n    };\n\n  } else if(\n    ( mapData = new RegExp( types.mapData.regex ).exec( value ) ) ||\n    ( mapLayoutData = new RegExp( types.mapLayoutData.regex ).exec( value ) ) ||\n    ( mapScratch = new RegExp( types.mapScratch.regex ).exec( value ) )\n  ){\n    if( propIsBypass ){ return false; } // mappers not allowed in bypass\n    if( type.multiple ){ return false; } // impossible to map to num\n\n    var mapped;\n    if( mapData ){\n      mapped = types.mapData;\n    } else if( mapLayoutData ){\n      mapped = types.mapLayoutData;\n    } else {\n      mapped = types.mapScratch;\n    }\n\n    mapData = mapData || mapLayoutData || mapScratch;\n\n    // we can map only if the type is a colour or a number\n    if( !(type.color || type.number) ){ return false; }\n\n    var valueMin = this.parse( name, mapData[4] ); // parse to validate\n    if( !valueMin || valueMin.mapped ){ return false; } // can't be invalid or mapped\n\n    var valueMax = this.parse( name, mapData[5] ); // parse to validate\n    if( !valueMax || valueMax.mapped ){ return false; } // can't be invalid or mapped\n\n    // check if valueMin and valueMax are the same\n    if( valueMin.value === valueMax.value ){\n      return false; // can't make much of a mapper without a range\n\n    } else if( type.color ){\n      var c1 = valueMin.value;\n      var c2 = valueMax.value;\n\n      var same = c1[0] === c2[0] // red\n        && c1[1] === c2[1] // green\n        && c1[2] === c2[2] // blue\n        && ( // optional alpha\n          c1[3] === c2[3] // same alpha outright\n          || (\n            (c1[3] == null || c1[3] === 1) // full opacity for colour 1?\n            &&\n            (c2[3] == null || c2[3] === 1) // full opacity for colour 2?\n          )\n        )\n      ;\n\n      if( same ){ return false; } // can't make a mapper without a range\n    }\n\n    return {\n      name: name,\n      value: mapData,\n      strValue: '' + value,\n      mapped: mapped,\n      field: mapData[1],\n      fieldMin: parseFloat( mapData[2] ), // min & max are numeric\n      fieldMax: parseFloat( mapData[3] ),\n      valueMin: valueMin.value,\n      valueMax: valueMax.value,\n      bypass: propIsBypass\n    };\n  }\n\n  if( type.multiple && propIsFlat !== 'multiple' ){\n    var vals;\n\n    if( valueIsString ){\n      vals = value.split(/\\s+/);\n    } else if( is.array(value) ){\n      vals = value;\n    } else {\n      vals = [ value ];\n    }\n\n    if( type.evenMultiple && vals.length % 2 !== 0 ){ return null; }\n\n    var valArr = vals.map(function( v ){\n      var p = self.parse( name, v, propIsBypass, 'multiple' );\n\n      if( p.pfValue != null ){\n        return p.pfValue;\n      } else {\n        return p.value;\n      }\n    });\n\n    return {\n      name: name,\n      value: valArr,\n      pfValue: valArr,\n      strValue: valArr.join(' '),\n      bypass: propIsBypass,\n      units: type.number && !type.unitless ? type.implicitUnits || 'px' : undefined\n    };\n  }\n\n  // several types also allow enums\n  var checkEnums = function(){\n    for( var i = 0; i < type.enums.length; i++ ){\n      var en = type.enums[i];\n\n      if( en === value ){\n        return {\n          name: name,\n          value: value,\n          strValue: '' + value,\n          bypass: propIsBypass\n        };\n      }\n    }\n\n    return null;\n  };\n\n  // check the type and return the appropriate object\n  if( type.number ){\n    var units;\n    var implicitUnits = 'px'; // not set => px\n\n    if( type.units ){ // use specified units if set\n      units = type.units;\n    }\n\n    if( type.implicitUnits ){\n      implicitUnits = type.implicitUnits;\n    }\n\n    if( !type.unitless ){\n      if( valueIsString ){\n        var unitsRegex = 'px|em' + (type.allowPercent ? '|\\\\%' : '');\n        if( units ){ unitsRegex = units; } // only allow explicit units if so set\n        var match = value.match( '^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$' );\n\n        if( match ){\n          value = match[1];\n          units = match[2] || implicitUnits;\n        }\n\n      } else if( !units || type.implicitUnits ) {\n        units = implicitUnits; // implicitly px if unspecified\n      }\n    }\n\n    value = parseFloat( value );\n\n    // if not a number and enums not allowed, then the value is invalid\n    if( isNaN(value) && type.enums === undefined ){\n      return null;\n    }\n\n    // check if this number type also accepts special keywords in place of numbers\n    // (i.e. `left`, `auto`, etc)\n    if( isNaN(value) && type.enums !== undefined ){\n      value = passedValue;\n\n      return checkEnums();\n    }\n\n    // check if value must be an integer\n    if( type.integer && !is.integer(value) ){\n      return null;\n    }\n\n    // check value is within range\n    if( (type.min !== undefined && value < type.min)\n    || (type.max !== undefined && value > type.max)\n    ){\n      return null;\n    }\n\n    var ret = {\n      name: name,\n      value: value,\n      strValue: '' + value + (units ? units : ''),\n      units: units,\n      bypass: propIsBypass\n    };\n\n    // normalise value in pixels\n    if( type.unitless || (units !== 'px' && units !== 'em') ){\n      ret.pfValue = value;\n    } else {\n      ret.pfValue = ( units === 'px' || !units ? (value) : (this.getEmSizeInPixels() * value) );\n    }\n\n    // normalise value in ms\n    if( units === 'ms' || units === 's' ){\n      ret.pfValue = units === 'ms' ? value : 1000 * value;\n    }\n\n    // normalise value in rad\n    if( units === 'deg' || units === 'rad' ){\n      ret.pfValue = units === 'rad' ? value : value * Math.PI/180;\n    }\n\n    return ret;\n\n  } else if( type.propList ) {\n\n    var props = [];\n    var propsStr = '' + value;\n\n    if( propsStr === 'none' ){\n      // leave empty\n\n    } else { // go over each prop\n\n      var propsSplit = propsStr.split(',');\n      for( var i = 0; i < propsSplit.length; i++ ){\n        var propName = propsSplit[i].trim();\n\n        if( self.properties[propName] ){\n          props.push( propName );\n        }\n      }\n\n      if( props.length === 0 ){ return null; }\n    }\n\n    return {\n      name: name,\n      value: props,\n      strValue: props.length === 0 ? 'none' : props.join(', '),\n      bypass: propIsBypass\n    };\n\n  } else if( type.color ){\n    var tuple = util.color2tuple( value );\n\n    if( !tuple ){ return null; }\n\n    return {\n      name: name,\n      value: tuple,\n      strValue: '' + value,\n      bypass: propIsBypass,\n      roundValue: true\n    };\n\n  } else if( type.regex || type.regexes ){\n\n    // first check enums\n    if( type.enums ){\n      var enumProp = checkEnums();\n\n      if( enumProp ){ return enumProp; }\n    }\n\n    var regexes = type.regexes ? type.regexes : [ type.regex ];\n\n    for( var i = 0; i < regexes.length; i++ ){\n      var regex = new RegExp( regexes[i] ); // make a regex from the type string\n      var m = regex.exec( value );\n\n      if( m ){ // regex matches\n        return {\n          name: name,\n          value: m,\n          strValue: '' + value,\n          bypass: propIsBypass\n        };\n\n      }\n    }\n\n    return null; // didn't match any\n\n  } else if( type.string ){\n    // just return\n    return {\n      name: name,\n      value: value,\n      strValue: '' + value,\n      bypass: propIsBypass\n    };\n\n  } else if( type.enums ){ // check enums last because it's a combo type in others\n    return checkEnums();\n\n  } else {\n    return null; // not a type we can handle\n  }\n\n};\n\nmodule.exports = styfn;\n\n},{\"../is\":77,\"../util\":94}],89:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\n\nvar styfn = {};\n\n(function(){\n  var number = util.regex.number;\n  var rgba = util.regex.rgbaNoBackRefs;\n  var hsla = util.regex.hslaNoBackRefs;\n  var hex3 = util.regex.hex3;\n  var hex6 = util.regex.hex6;\n  var data = function( prefix ){ return '^' + prefix + '\\\\s*\\\\(\\\\s*([\\\\w\\\\.]+)\\\\s*\\\\)$'; };\n  var mapData = function( prefix ){\n    var mapArg = number + '|\\\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6;\n    return '^' + prefix + '\\\\s*\\\\(([\\\\w\\\\.]+)\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + mapArg + ')\\\\s*\\\\,\\\\s*(' + mapArg + ')\\\\)$';\n  };\n\n  // each visual style property has a type and needs to be validated according to it\n  styfn.types = {\n    time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' },\n    percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' },\n    zeroOneNumber: { number: true, min: 0, max: 1, unitless: true },\n    nOneOneNumber: { number: true, min: -1, max: 1, unitless: true },\n    nonNegativeInt: { number: true, min: 0, integer: true, unitless: true },\n    position: { enums: ['parent', 'origin'] },\n    nodeSize: { number: true, min: 0, enums: ['auto', 'label'] },\n    number: { number: true, unitless: true },\n    numbers: { number: true, unitless: true, multiple: true },\n    size: { number: true, min: 0 },\n    bidirectionalSize: { number: true }, // allows negative\n    bidirectionalSizes: { number: true, multiple: true }, // allows negative\n    bgSize: { number: true, min: 0, allowPercent: true },\n    bgWH: { number: true, min: 0, allowPercent: true, enums: ['auto'] },\n    bgPos: { number: true, allowPercent: true },\n    bgRepeat: { enums: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'] },\n    bgFit: { enums: ['none', 'contain', 'cover'] },\n    bgClip: { enums: ['none', 'node'] },\n    color: { color: true },\n    bool: { enums: ['yes', 'no'] },\n    lineStyle: { enums: ['solid', 'dotted', 'dashed'] },\n    borderStyle: { enums: ['solid', 'dotted', 'dashed', 'double'] },\n    curveStyle: { enums: ['bezier', 'unbundled-bezier', 'haystack', 'segments'] },\n    fontFamily: { regex: '^([\\\\w- \\\\\"]+(?:\\\\s*,\\\\s*[\\\\w- \\\\\"]+)*)$' },\n    fontVariant: { enums: ['small-caps', 'normal'] },\n    fontStyle: { enums: ['italic', 'normal', 'oblique'] },\n    fontWeight: { enums: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900] },\n    textDecoration: { enums: ['none', 'underline', 'overline', 'line-through'] },\n    textTransform: { enums: ['none', 'uppercase', 'lowercase'] },\n    textWrap: { enums: ['none', 'wrap'] },\n    textBackgroundShape: { enums: ['rectangle', 'roundrectangle']},\n    nodeShape: { enums: ['rectangle', 'roundrectangle', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'diamond', 'vee', 'rhomboid', 'polygon'] },\n    compoundIncludeLabels: { enums: ['include', 'exclude'] },\n    arrowShape: { enums: ['tee', 'triangle', 'triangle-tee', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none'] },\n    arrowFill: { enums: ['filled', 'hollow'] },\n    display: { enums: ['element', 'none'] },\n    visibility: { enums: ['hidden', 'visible'] },\n    valign: { enums: ['top', 'center', 'bottom'] },\n    halign: { enums: ['left', 'center', 'right'] },\n    text: { string: true },\n    data: { mapping: true, regex: data('data') },\n    layoutData: { mapping: true, regex: data('layoutData') },\n    scratch: { mapping: true, regex: data('scratch') },\n    mapData: { mapping: true, regex: mapData('mapData') },\n    mapLayoutData: { mapping: true, regex: mapData('mapLayoutData') },\n    mapScratch: { mapping: true, regex: mapData('mapScratch') },\n    fn: { mapping: true, fn: true },\n    url: { regex: '^url\\\\s*\\\\(\\\\s*([^\\\\s]+)\\\\s*\\\\s*\\\\)|none|(.+)$' },\n    propList: { propList: true },\n    angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' },\n    textRotation: { enums: ['none', 'autorotate'] },\n    polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true },\n    easing: {\n      regexes: [\n        '^(spring)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$',\n        '^(cubic-bezier)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$'\n      ],\n      enums: [\n        'linear',\n        'ease', 'ease-in', 'ease-out', 'ease-in-out',\n        'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine',\n        'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad',\n        'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic',\n        'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart',\n        'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint',\n        'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo',\n        'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ'\n      ]\n    }\n  };\n\n  // define visual style properties\n  var t = styfn.types;\n  var props = styfn.properties = [\n    // labels\n    { name: 'text-valign', type: t.valign },\n    { name: 'text-halign', type: t.halign },\n    { name: 'color', type: t.color },\n    { name: 'label', type: t.text },\n    { name: 'text-outline-color', type: t.color },\n    { name: 'text-outline-width', type: t.size },\n    { name: 'text-outline-opacity', type: t.zeroOneNumber },\n    { name: 'text-opacity', type: t.zeroOneNumber },\n    { name: 'text-background-color', type: t.color },\n    { name: 'text-background-opacity', type: t.zeroOneNumber },\n    { name: 'text-border-opacity', type: t.zeroOneNumber },\n    { name: 'text-border-color', type: t.color },\n    { name: 'text-border-width', type: t.size },\n    { name: 'text-border-style', type: t.borderStyle },\n    { name: 'text-background-shape', type: t.textBackgroundShape},\n    // { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas\n    { name: 'text-transform', type: t.textTransform },\n    { name: 'text-wrap', type: t.textWrap },\n    { name: 'text-max-width', type: t.size },\n    { name: 'text-events', type: t.bool },\n\n    // { name: 'text-rotation', type: t.angle }, // TODO disabled b/c rotation breaks bounding boxes\n    { name: 'font-family', type: t.fontFamily },\n    { name: 'font-style', type: t.fontStyle },\n    // { name: 'font-variant', type: t.fontVariant }, // not useful\n    { name: 'font-weight', type: t.fontWeight },\n    { name: 'font-size', type: t.size },\n    { name: 'min-zoomed-font-size', type: t.size },\n    { name: 'edge-text-rotation', type: t.textRotation },\n\n    // behaviour\n    { name: 'events', type: t.bool },\n\n    // visibility\n    { name: 'display', type: t.display },\n    { name: 'visibility', type: t.visibility },\n    { name: 'opacity', type: t.zeroOneNumber },\n    { name: 'z-index', type: t.nonNegativeInt },\n\n    // overlays\n    { name: 'overlay-padding', type: t.size },\n    { name: 'overlay-color', type: t.color },\n    { name: 'overlay-opacity', type: t.zeroOneNumber },\n\n    // shadows\n    { name: 'shadow-blur', type: t.size },\n    { name: 'shadow-color', type: t.color },\n    { name: 'shadow-opacity', type: t.zeroOneNumber },\n    { name: 'shadow-offset-x', type: t.bidirectionalSize },\n    { name: 'shadow-offset-y', type: t.bidirectionalSize },\n\n    // label shadows\n    { name: 'text-shadow-blur', type: t.size },\n    { name: 'text-shadow-color', type: t.color },\n    { name: 'text-shadow-opacity', type: t.zeroOneNumber },\n    { name: 'text-shadow-offset-x', type: t.bidirectionalSize },\n    { name: 'text-shadow-offset-y', type: t.bidirectionalSize },\n\n    // transition anis\n    { name: 'transition-property', type: t.propList },\n    { name: 'transition-duration', type: t.time },\n    { name: 'transition-delay', type: t.time },\n    { name: 'transition-timing-function', type: t.easing },\n\n    // node body\n    { name: 'height', type: t.nodeSize },\n    { name: 'width', type: t.nodeSize },\n    { name: 'shape', type: t.nodeShape },\n    { name: 'shape-polygon-points', type: t.polygonPointList },\n    { name: 'background-color', type: t.color },\n    { name: 'background-opacity', type: t.zeroOneNumber },\n    { name: 'background-blacken', type: t.nOneOneNumber },\n    { name: 'padding-left', type: t.size },\n    { name: 'padding-right', type: t.size },\n    { name: 'padding-top', type: t.size },\n    { name: 'padding-bottom', type: t.size },\n\n    // node border\n    { name: 'border-color', type: t.color },\n    { name: 'border-opacity', type: t.zeroOneNumber },\n    { name: 'border-width', type: t.size },\n    { name: 'border-style', type: t.borderStyle },\n\n    // node background images\n    { name: 'background-image', type: t.url },\n    { name: 'background-image-opacity', type: t.zeroOneNumber },\n    { name: 'background-position-x', type: t.bgPos },\n    { name: 'background-position-y', type: t.bgPos },\n    { name: 'background-repeat', type: t.bgRepeat },\n    { name: 'background-fit', type: t.bgFit },\n    { name: 'background-clip', type: t.bgClip },\n    { name: 'background-width', type: t.bgWH },\n    { name: 'background-height', type: t.bgWH },\n\n    // compound props\n    { name: 'position', type: t.position },\n    { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels },\n\n    // edge line\n    { name: 'line-style', type: t.lineStyle },\n    { name: 'line-color', type: t.color },\n    { name: 'curve-style', type: t.curveStyle },\n    { name: 'haystack-radius', type: t.zeroOneNumber },\n    { name: 'control-point-step-size', type: t.size },\n    { name: 'control-point-distances', type: t.bidirectionalSizes },\n    { name: 'control-point-weights', type: t.numbers },\n    { name: 'segment-distances', type: t.bidirectionalSizes },\n    { name: 'segment-weights', type: t.numbers },\n\n    // these are just for the core\n    { name: 'selection-box-color', type: t.color },\n    { name: 'selection-box-opacity', type: t.zeroOneNumber },\n    { name: 'selection-box-border-color', type: t.color },\n    { name: 'selection-box-border-width', type: t.size },\n    { name: 'active-bg-color', type: t.color },\n    { name: 'active-bg-opacity', type: t.zeroOneNumber },\n    { name: 'active-bg-size', type: t.size },\n    { name: 'outside-texture-bg-color', type: t.color },\n    { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber }\n  ];\n\n  // define aliases\n  var aliases = styfn.aliases = [\n    { name: 'content', pointsTo: 'label' },\n    { name: 'control-point-distance', pointsTo: 'control-point-distances' },\n    { name: 'control-point-weight', pointsTo: 'control-point-weights' }\n  ];\n\n  // pie backgrounds for nodes\n  styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use)\n  props.push({ name: 'pie-size', type: t.bgSize });\n  for( var i = 1; i <= styfn.pieBackgroundN; i++ ){\n    props.push({ name: 'pie-'+i+'-background-color', type: t.color });\n    props.push({ name: 'pie-'+i+'-background-size', type: t.percent });\n    props.push({ name: 'pie-'+i+'-background-opacity', type: t.zeroOneNumber });\n  }\n\n  // edge arrows\n  var arrowPrefixes = styfn.arrowPrefixes = ['source', 'mid-source', 'target', 'mid-target'];\n  [\n    { name: 'arrow-shape', type: t.arrowShape },\n    { name: 'arrow-color', type: t.color },\n    { name: 'arrow-fill', type: t.arrowFill }\n  ].forEach(function( prop ){\n    arrowPrefixes.forEach(function( prefix ){\n      var name = prefix + '-' + prop.name;\n      var type = prop.type;\n\n      props.push({ name: name, type: type });\n    });\n  }, {});\n\n  // list of property names\n  styfn.propertyNames = props.map(function(p){ return p.name; });\n\n  // allow access of properties by name ( e.g. style.properties.height )\n  for( var i = 0; i < props.length; i++ ){\n    var prop = props[i];\n\n    props[ prop.name ] = prop; // allow lookup by name\n  }\n\n  // map aliases\n  for( var i = 0; i < aliases.length; i++ ){\n    var alias = aliases[i];\n    var pointsToProp = props[ alias.pointsTo ];\n    var aliasProp = {\n      name: alias.name,\n      alias: true,\n      pointsTo: pointsToProp\n    };\n\n    // add alias prop for parsing\n    props.push( aliasProp );\n\n    props[ alias.name ] = aliasProp; // allow lookup by name\n  }\n})();\n\n// adds the default stylesheet to the current style\nstyfn.addDefaultStylesheet = function(){\n  // fill the style with the default stylesheet\n  this\n    .selector('node, edge') // common properties\n      .css( util.extend( {\n        'events': 'yes',\n        'text-events': 'no',\n        'text-valign': 'top',\n        'text-halign': 'center',\n        'color': '#000',\n        'text-outline-color': '#000',\n        'text-outline-width': 0,\n        'text-outline-opacity': 1,\n        'text-opacity': 1,\n        'text-decoration': 'none',\n        'text-transform': 'none',\n        'text-wrap': 'none',\n        'text-max-width': 9999,\n        'text-background-color': '#000',\n        'text-background-opacity': 0,\n        'text-border-opacity': 0,\n        'text-border-width': 0,\n        'text-border-style': 'solid',\n        'text-border-color':'#000',\n        'text-background-shape':'rectangle',\n        'font-family': 'Helvetica Neue, Helvetica, sans-serif',\n        'font-style': 'normal',\n        // 'font-variant': fontVariant,\n        'font-weight': 'normal',\n        'font-size': 16,\n        'min-zoomed-font-size': 0,\n        'edge-text-rotation': 'none',\n        'visibility': 'visible',\n        'display': 'element',\n        'opacity': 1,\n        'z-index': 0,\n        'label': '',\n        'overlay-opacity': 0,\n        'overlay-color': '#000',\n        'overlay-padding': 10,\n        'shadow-opacity': 0,\n        'shadow-color': '#000',\n        'shadow-blur': 10,\n        'shadow-offset-x': 0,\n        'shadow-offset-y': 0,\n        'text-shadow-opacity': 0,\n        'text-shadow-color': '#000',\n        'text-shadow-blur': 5,\n        'text-shadow-offset-x': 0,\n        'text-shadow-offset-y': 0,\n        'transition-property': 'none',\n        'transition-duration': 0,\n        'transition-delay': 0,\n        'transition-timing-function': 'linear',\n\n        // node props\n        'background-blacken': 0,\n        'background-color': '#888',\n        'background-opacity': 1,\n        'background-image': 'none',\n        'background-image-opacity': 1,\n        'background-position-x': '50%',\n        'background-position-y': '50%',\n        'background-repeat': 'no-repeat',\n        'background-fit': 'none',\n        'background-clip': 'node',\n        'background-width': 'auto',\n        'background-height': 'auto',\n        'border-color': '#000',\n        'border-opacity': 1,\n        'border-width': 0,\n        'border-style': 'solid',\n        'height': 30,\n        'width': 30,\n        'shape': 'ellipse',\n        'shape-polygon-points': '-1, -1,   1, -1,   1, 1,   -1, 1',\n\n        // compound props\n        'padding-top': 0,\n        'padding-bottom': 0,\n        'padding-left': 0,\n        'padding-right': 0,\n        'position': 'origin',\n        'compound-sizing-wrt-labels': 'include'\n      }, {\n        // node pie bg\n        'pie-size': '100%'\n      }, [\n        { name: 'pie-{{i}}-background-color', value: 'black' },\n        { name: 'pie-{{i}}-background-size', value: '0%' },\n        { name: 'pie-{{i}}-background-opacity', value: 1 }\n      ].reduce(function( css, prop ){\n        for( var i = 1; i <= styfn.pieBackgroundN; i++ ){\n          var name = prop.name.replace('{{i}}', i);\n          var val = prop.value;\n\n          css[ name ] = val;\n        }\n\n        return css;\n      }, {}), {\n        // edge props\n        'line-style': 'solid',\n        'line-color': '#ddd',\n        'control-point-step-size': 40,\n        'control-point-weights': 0.5,\n        'segment-weights': 0.5,\n        'segment-distances': 20,\n        'curve-style': 'bezier',\n        'haystack-radius': 0.8\n      }, [\n        { name: 'arrow-shape', value: 'none' },\n        { name: 'arrow-color', value: '#ddd' },\n        { name: 'arrow-fill', value: 'filled' }\n      ].reduce(function( css, prop ){\n        styfn.arrowPrefixes.forEach(function( prefix ){\n          var name = prefix + '-' + prop.name;\n          var val = prop.value;\n\n          css[ name ] = val;\n        });\n\n        return css;\n      }, {}) ) )\n    .selector('$node > node') // compound (parent) node properties\n      .css({\n        'width': 'auto',\n        'height': 'auto',\n        'shape': 'rectangle',\n        'padding-top': 10,\n        'padding-right': 10,\n        'padding-left': 10,\n        'padding-bottom': 10\n      })\n    .selector('edge') // just edge properties\n      .css({\n        'width': 1\n      })\n    .selector(':active')\n      .css({\n        'overlay-color': 'black',\n        'overlay-padding': 10,\n        'overlay-opacity': 0.25\n      })\n    .selector('core') // just core properties\n      .css({\n        'selection-box-color': '#ddd',\n        'selection-box-opacity': 0.65,\n        'selection-box-border-color': '#aaa',\n        'selection-box-border-width': 1,\n        'active-bg-color': 'black',\n        'active-bg-opacity': 0.15,\n        'active-bg-size': 30,\n        'outside-texture-bg-color': '#000',\n        'outside-texture-bg-opacity': 0.125\n      })\n  ;\n\n  this.defaultLength = this.length;\n};\n\nmodule.exports = styfn;\n\n},{\"../util\":94}],90:[function(_dereq_,module,exports){\n'use strict';\n\nvar util = _dereq_('../util');\nvar Selector = _dereq_('../selector');\n\nvar styfn = {};\n\nstyfn.applyFromString = function( string ){\n  var self = this;\n  var style = this;\n  var remaining = '' + string;\n  var selAndBlockStr;\n  var blockRem;\n  var propAndValStr;\n\n  // remove comments from the style string\n  remaining = remaining.replace(/[/][*](\\s|.)+?[*][/]/g, '');\n\n  function removeSelAndBlockFromRemaining(){\n    // remove the parsed selector and block from the remaining text to parse\n    if( remaining.length > selAndBlockStr.length ){\n      remaining = remaining.substr( selAndBlockStr.length );\n    } else {\n      remaining = '';\n    }\n  }\n\n  function removePropAndValFromRem(){\n    // remove the parsed property and value from the remaining block text to parse\n    if( blockRem.length > propAndValStr.length ){\n      blockRem = blockRem.substr( propAndValStr.length );\n    } else {\n      blockRem = '';\n    }\n  }\n\n  while(true){\n    var nothingLeftToParse = remaining.match(/^\\s*$/);\n    if( nothingLeftToParse ){ break; }\n\n    var selAndBlock = remaining.match(/^\\s*((?:.|\\s)+?)\\s*\\{((?:.|\\s)+?)\\}/);\n\n    if( !selAndBlock ){\n      util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);\n      break;\n    }\n\n    selAndBlockStr = selAndBlock[0];\n\n    // parse the selector\n    var selectorStr = selAndBlock[1];\n    if( selectorStr !== 'core' ){\n      var selector = new Selector( selectorStr );\n      if( selector._private.invalid ){\n        util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr);\n\n        // skip this selector and block\n        removeSelAndBlockFromRemaining();\n        continue;\n      }\n    }\n\n    // parse the block of properties and values\n    var blockStr = selAndBlock[2];\n    var invalidBlock = false;\n    blockRem = blockStr;\n    var props = [];\n\n    while(true){\n      var nothingLeftToParse = blockRem.match(/^\\s*$/);\n      if( nothingLeftToParse ){ break; }\n\n      var propAndVal = blockRem.match(/^\\s*(.+?)\\s*:\\s*(.+?)\\s*;/);\n\n      if( !propAndVal ){\n        util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);\n        invalidBlock = true;\n        break;\n      }\n\n      propAndValStr = propAndVal[0];\n      var propStr = propAndVal[1];\n      var valStr = propAndVal[2];\n\n      var prop = self.properties[ propStr ];\n      if( !prop ){\n        util.error('Skipping property: Invalid property name in: ' + propAndValStr);\n\n        // skip this property in the block\n        removePropAndValFromRem();\n        continue;\n      }\n\n      var parsedProp = style.parse( propStr, valStr );\n\n      if( !parsedProp ){\n        util.error('Skipping property: Invalid property definition in: ' + propAndValStr);\n\n        // skip this property in the block\n        removePropAndValFromRem();\n        continue;\n      }\n\n      props.push({\n        name: propStr,\n        val: valStr\n      });\n      removePropAndValFromRem();\n    }\n\n    if( invalidBlock ){\n      removeSelAndBlockFromRemaining();\n      break;\n    }\n\n    // put the parsed block in the style\n    style.selector( selectorStr );\n    for( var i = 0; i < props.length; i++ ){\n      var prop = props[i];\n      style.css( prop.name, prop.val );\n    }\n\n    removeSelAndBlockFromRemaining();\n  }\n\n  return style;\n};\n\nstyfn.fromString = function( string ){\n  var style = this;\n\n  style.resetToDefault();\n  style.applyFromString( string );\n\n  return style;\n};\n\nmodule.exports = styfn;\n\n},{\"../selector\":81,\"../util\":94}],91:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('./is');\nvar util = _dereq_('./util');\nvar Style = _dereq_('./style');\n\n// a dummy stylesheet object that doesn't need a reference to the core\n// (useful for init)\nvar Stylesheet = function(){\n  if( !(this instanceof Stylesheet) ){\n    return new Stylesheet();\n  }\n\n  this.length = 0;\n};\n\nvar sheetfn = Stylesheet.prototype;\n\nsheetfn.instanceString = function(){\n  return 'stylesheet';\n};\n\n// just store the selector to be parsed later\nsheetfn.selector = function( selector ){\n  var i = this.length++;\n\n  this[i] = {\n    selector: selector,\n    properties: []\n  };\n\n  return this; // chaining\n};\n\n// just store the property to be parsed later\nsheetfn.css = function( name, value ){\n  var i = this.length - 1;\n\n  if( is.string(name) ){\n    this[i].properties.push({\n      name: name,\n      value: value\n    });\n  } else if( is.plainObject(name) ){\n    var map = name;\n\n    for( var j = 0; j < Style.properties.length; j++ ){\n      var prop = Style.properties[j];\n      var mapVal = map[ prop.name ];\n\n      if( mapVal === undefined ){ // also try camel case name\n        mapVal = map[ util.dash2camel(prop.name) ];\n      }\n\n      if( mapVal !== undefined ){\n        var name = prop.name;\n        var value = mapVal;\n\n        this[i].properties.push({\n          name: name,\n          value: value\n        });\n      }\n    }\n  }\n\n  return this; // chaining\n};\n\nsheetfn.style = sheetfn.css;\n\n// generate a real style object from the dummy stylesheet\nsheetfn.generateStyle = function( cy ){\n  var style = new Style(cy);\n\n  for( var i = 0; i < this.length; i++ ){\n    var context = this[i];\n    var selector = context.selector;\n    var props = context.properties;\n\n    style.selector(selector); // apply selector\n\n    for( var j = 0; j < props.length; j++ ){\n      var prop = props[j];\n\n      style.css( prop.name, prop.value ); // apply property\n    }\n  }\n\n  return style;\n};\n\nmodule.exports = Stylesheet;\n\n},{\"./is\":77,\"./style\":86,\"./util\":94}],92:[function(_dereq_,module,exports){\n// cross-env thread/worker\n// NB : uses (heavyweight) processes on nodejs so best not to create too many threads\n\n'use strict';\n\nvar window = _dereq_('./window');\nvar util = _dereq_('./util');\nvar Promise = _dereq_('./promise');\nvar Event = _dereq_('./event');\nvar define = _dereq_('./define');\nvar is = _dereq_('./is');\n\nvar Thread = function( opts ){\n  if( !(this instanceof Thread) ){\n    return new Thread( opts );\n  }\n\n  var _p = this._private = {\n    requires: [],\n    files: [],\n    queue: null,\n    pass: [],\n    disabled: false\n  };\n\n  if( is.plainObject(opts) ){\n    if( opts.disabled != null ){\n      _p.disabled = !!opts.disabled;\n    }\n  }\n\n};\n\nvar thdfn = Thread.prototype; // short alias\n\nvar stringifyFieldVal = function( val ){\n  var valStr = is.fn( val ) ? val.toString() : 'JSON.parse(\"' + JSON.stringify(val) + '\")';\n\n  return valStr;\n};\n\n// allows for requires with prototypes and subobjs etc\nvar fnAsRequire = function( fn ){\n  var req;\n  var fnName;\n\n  if( is.object(fn) && fn.fn ){ // manual fn\n    req = fnAs( fn.fn, fn.name );\n    fnName = fn.name;\n    fn = fn.fn;\n  } else if( is.fn(fn) ){ // auto fn\n    req = fn.toString();\n    fnName = fn.name;\n  } else if( is.string(fn) ){ // stringified fn\n    req = fn;\n  } else if( is.object(fn) ){ // plain object\n    if( fn.proto ){\n      req = '';\n    } else {\n      req = fn.name + ' = {};';\n    }\n\n    fnName = fn.name;\n    fn = fn.obj;\n  }\n\n  req += '\\n';\n\n  var protoreq = function( val, subname ){\n    if( val.prototype ){\n      var protoNonempty = false;\n      for( var prop in val.prototype ){ protoNonempty = true; break; } // jshint ignore:line\n\n      if( protoNonempty ){\n        req += fnAsRequire( {\n          name: subname,\n          obj: val,\n          proto: true\n        }, val );\n      }\n    }\n  };\n\n  // pull in prototype\n  if( fn.prototype && fnName != null ){\n\n    for( var name in fn.prototype ){\n      var protoStr = '';\n\n      var val = fn.prototype[ name ];\n      var valStr = stringifyFieldVal( val );\n      var subname = fnName + '.prototype.' + name;\n\n      protoStr += subname + ' = ' + valStr + ';\\n';\n\n      if( protoStr ){\n        req += protoStr;\n      }\n\n      protoreq( val, subname ); // subobject with prototype\n    }\n\n  }\n\n  // pull in properties for obj/fns\n  if( !is.string(fn) ){ for( var name in fn ){\n    var propsStr = '';\n\n    if( fn.hasOwnProperty(name) ){\n      var val = fn[ name ];\n      var valStr = stringifyFieldVal( val );\n      var subname = fnName + '[\"' + name + '\"]';\n\n      propsStr += subname + ' = ' + valStr + ';\\n';\n    }\n\n    if( propsStr ){\n      req += propsStr;\n    }\n\n    protoreq( val, subname ); // subobject with prototype\n  } }\n\n  return req;\n};\n\nvar isPathStr = function( str ){\n  return is.string(str) && str.match(/\\.js$/);\n};\n\nutil.extend(thdfn, {\n\n  instanceString: function(){ return 'thread'; },\n\n  require: function( fn, as ){\n    var requires = this._private.requires;\n\n    if( isPathStr(fn) ){\n      this._private.files.push( fn );\n\n      return this;\n    }\n\n    if( as ){\n      if( is.fn(fn) ){\n        fn = { name: as, fn: fn };\n      } else {\n        fn = { name: as, obj: fn };\n      }\n    } else {\n      if( is.fn(fn) ){\n        if( !fn.name ){\n          throw 'The function name could not be automatically determined.  Use thread.require( someFunction, \"someFunction\" )';\n        }\n\n        fn = { name: fn.name, fn: fn };\n      }\n    }\n\n    requires.push( fn );\n\n    return this; // chaining\n  },\n\n  pass: function( data ){\n    this._private.pass.push( data );\n\n    return this; // chaining\n  },\n\n  run: function( fn, pass ){ // fn used like main()\n    var self = this;\n    var _p = this._private;\n    pass = pass || _p.pass.shift();\n\n    if( _p.stopped ){\n      throw 'Attempted to run a stopped thread!  Start a new thread or do not stop the existing thread and reuse it.';\n    }\n\n    if( _p.running ){\n      return ( _p.queue = _p.queue.then(function(){ // inductive step\n        return self.run( fn, pass );\n      }) );\n    }\n\n    var useWW = window != null && !_p.disabled;\n    var useNode = !window && typeof module !== 'undefined' && !_p.disabled;\n\n    self.trigger('run');\n\n    var runP = new Promise(function( resolve, reject ){\n\n      _p.running = true;\n\n      var threadTechAlreadyExists = _p.ran;\n\n      var fnImplStr = is.string( fn ) ? fn : fn.toString();\n\n      // worker code to exec\n      var fnStr = '\\n' + ( _p.requires.map(function( r ){\n        return fnAsRequire( r );\n      }) ).concat( _p.files.map(function( f ){\n        if( useWW ){\n          var wwifyFile = function( file ){\n            if( file.match(/^\\.\\//) || file.match(/^\\.\\./) ){\n              return window.location.origin + window.location.pathname + file;\n            } else if( file.match(/^\\//) ){\n              return window.location.origin + '/' + file;\n            }\n            return file;\n          };\n\n          return 'importScripts(\"' + wwifyFile(f) + '\");';\n        } else if( useNode ) {\n          return 'eval( require(\"fs\").readFileSync(\"' + f + '\", { encoding: \"utf8\" }) );';\n        } else {\n          throw 'External file `' + f + '` can not be required without any threading technology.';\n        }\n      }) ).concat([\n        '( function(){',\n          'var ret = (' + fnImplStr + ')(' + JSON.stringify(pass) + ');',\n          'if( ret !== undefined ){ resolve(ret); }', // assume if ran fn returns defined value (incl. null), that we want to resolve to it\n        '} )()\\n'\n      ]).join('\\n');\n\n      // because we've now consumed the requires, empty the list so we don't dupe on next run()\n      _p.requires = [];\n      _p.files = [];\n\n      if( useWW ){\n        var fnBlob, fnUrl;\n\n        // add normalised thread api functions\n        if( !threadTechAlreadyExists ){\n          var fnPre = fnStr + '';\n\n          fnStr = [\n            'function _ref_(o){ return eval(o); };',\n            'function broadcast(m){ return message(m); };', // alias\n            'function message(m){ postMessage(m); };',\n            'function listen(fn){',\n            '  self.addEventListener(\"message\", function(m){ ',\n            '    if( typeof m === \"object\" && (m.data.$$eval || m.data === \"$$start\") ){',\n            '    } else { ',\n            '      fn( m.data );',\n            '    }',\n            '  });',\n            '};',\n            'self.addEventListener(\"message\", function(m){  if( m.data.$$eval ){ eval( m.data.$$eval ); }  });',\n            'function resolve(v){ postMessage({ $$resolve: v }); };',\n            'function reject(v){ postMessage({ $$reject: v }); };'\n          ].join('\\n');\n\n          fnStr += fnPre;\n\n          fnBlob = new Blob([ fnStr ], {\n            type: 'application/javascript'\n          });\n          fnUrl = window.URL.createObjectURL( fnBlob );\n        }\n        // create webworker and let it exec the serialised code\n        var ww = _p.webworker = _p.webworker || new Worker( fnUrl );\n\n        if( threadTechAlreadyExists ){ // then just exec new run() code\n          ww.postMessage({\n            $$eval: fnStr\n          });\n        }\n\n        // worker messages => events\n        var cb;\n        ww.addEventListener('message', cb = function( m ){\n          var isObject = is.object(m) && is.object( m.data );\n\n          if( isObject && ('$$resolve' in m.data) ){\n            ww.removeEventListener('message', cb); // done listening b/c resolve()\n\n            resolve( m.data.$$resolve );\n          } else if( isObject && ('$$reject' in m.data) ){\n            ww.removeEventListener('message', cb); // done listening b/c reject()\n\n            reject( m.data.$$reject );\n          } else {\n            self.trigger( new Event(m, { type: 'message', message: m.data }) );\n          }\n        }, false);\n\n        if( !threadTechAlreadyExists ){\n          ww.postMessage('$$start'); // start up the worker\n        }\n\n      } else if( useNode ){\n        // create a new process\n\n        if( !_p.child ){\n          _p.child = ( _dereq_('child_process').fork( _dereq_('path').join(__dirname, 'thread-node-fork') ) );\n        }\n\n        var child = _p.child;\n\n        // child process messages => events\n        var cb;\n        child.on('message', cb = function( m ){\n          if( is.object(m) && ('$$resolve' in m) ){\n            child.removeListener('message', cb); // done listening b/c resolve()\n\n            resolve( m.$$resolve );\n          } else if( is.object(m) && ('$$reject' in m) ){\n            child.removeListener('message', cb); // done listening b/c reject()\n\n            reject( m.$$reject );\n          } else {\n            self.trigger( new Event({}, { type: 'message', message: m }) );\n          }\n        });\n\n        // ask the child process to eval the worker code\n        child.send({\n          $$eval: fnStr\n        });\n\n      } else { // use a fallback mechanism using a timeout\n\n        var promiseResolve = resolve;\n        var promiseReject = reject;\n\n        var timer = _p.timer = _p.timer || {\n\n          listeners: [],\n\n          exec: function(){\n            // as a string so it can't be mangled by minifiers and processors\n            fnStr = [\n              'function _ref_(o){ return eval(o); };',\n              'function broadcast(m){ return message(m); };',\n              'function message(m){ self.trigger( new Event({}, { type: \"message\", message: m }) ); };',\n              'function listen(fn){ timer.listeners.push( fn ); };',\n              'function resolve(v){ promiseResolve(v); };',\n              'function reject(v){ promiseReject(v); };'\n            ].join('\\n') + fnStr;\n\n            // the .run() code\n            eval( fnStr ); // jshint ignore:line\n          },\n\n          message: function( m ){\n            var ls = timer.listeners;\n\n            for( var i = 0; i < ls.length; i++ ){\n              var fn = ls[i];\n\n              fn( m );\n            }\n          }\n\n        };\n\n        timer.exec();\n      }\n\n    }).then(function( v ){\n      _p.running = false;\n      _p.ran = true;\n\n      self.trigger('ran');\n\n      return v;\n    });\n\n    if( _p.queue == null ){\n      _p.queue = runP; // i.e. first step of inductive promise chain (for queue)\n    }\n\n    return runP;\n  },\n\n  // send the thread a message\n  message: function( m ){\n    var _p = this._private;\n\n    if( _p.webworker ){\n      _p.webworker.postMessage( m );\n    }\n\n    if( _p.child ){\n      _p.child.send( m );\n    }\n\n    if( _p.timer ){\n      _p.timer.message( m );\n    }\n\n    return this; // chaining\n  },\n\n  stop: function(){\n    var _p = this._private;\n\n    if( _p.webworker ){\n      _p.webworker.terminate();\n    }\n\n    if( _p.child ){\n      _p.child.kill();\n    }\n\n    if( _p.timer ){\n      // nothing we can do if we've run a timeout\n    }\n\n    _p.stopped = true;\n\n    return this.trigger('stop'); // chaining\n  },\n\n  stopped: function(){\n    return this._private.stopped;\n  }\n\n});\n\n// turns a stringified function into a (re)named function\nvar fnAs = function( fn, name ){\n  var fnStr = fn.toString();\n  fnStr = fnStr.replace(/function\\s*?\\S*?\\s*?\\(/, 'function ' + name + '(');\n\n  return fnStr;\n};\n\nvar defineFnal = function( opts ){\n  opts = opts || {};\n\n  return function fnalImpl( fn, arg1 ){\n    var fnStr = fnAs( fn, '_$_$_' + opts.name );\n\n    this.require( fnStr );\n\n    return this.run( [\n      'function( data ){',\n      '  var origResolve = resolve;',\n      '  var res = [];',\n      '  ',\n      '  resolve = function( val ){',\n      '    res.push( val );',\n      '  };',\n      '  ',\n      '  var ret = data.' + opts.name + '( _$_$_' + opts.name + ( arguments.length > 1 ? ', ' + JSON.stringify(arg1) : '' ) + ' );',\n      '  ',\n      '  resolve = origResolve;',\n      '  resolve( res.length > 0 ? res : ret );',\n      '}'\n    ].join('\\n') );\n  };\n};\n\nutil.extend(thdfn, {\n  reduce: defineFnal({ name: 'reduce' }),\n\n  reduceRight: defineFnal({ name: 'reduceRight' }),\n\n  map: defineFnal({ name: 'map' })\n});\n\n// aliases\nvar fn = thdfn;\nfn.promise = fn.run;\nfn.terminate = fn.halt = fn.stop;\nfn.include = fn.require;\n\n// pull in event apis\nutil.extend(thdfn, {\n  on: define.on(),\n  one: define.on({ unbindSelfOnTrigger: true }),\n  off: define.off(),\n  trigger: define.trigger()\n});\n\ndefine.eventAliasesOn( thdfn );\n\nmodule.exports = Thread;\n\n},{\"./define\":41,\"./event\":42,\"./is\":77,\"./promise\":80,\"./util\":94,\"./window\":100,\"child_process\":undefined,\"path\":undefined}],93:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\n\nmodule.exports = {\n  // get [r, g, b] from #abc or #aabbcc\n  hex2tuple: function( hex ){\n    if( !(hex.length === 4 || hex.length === 7) || hex[0] !== \"#\" ){ return; }\n\n    var shortHex = hex.length === 4;\n    var r, g, b;\n    var base = 16;\n\n    if( shortHex ){\n      r = parseInt( hex[1] + hex[1], base );\n      g = parseInt( hex[2] + hex[2], base );\n      b = parseInt( hex[3] + hex[3], base );\n    } else {\n      r = parseInt( hex[1] + hex[2], base );\n      g = parseInt( hex[3] + hex[4], base );\n      b = parseInt( hex[5] + hex[6], base );\n    }\n\n    return [r, g, b];\n  },\n\n  // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0)\n  hsl2tuple: function( hsl ){\n    var ret;\n    var h, s, l, a, r, g, b;\n    function hue2rgb(p, q, t){\n      if(t < 0) t += 1;\n      if(t > 1) t -= 1;\n      if(t < 1/6) return p + (q - p) * 6 * t;\n      if(t < 1/2) return q;\n      if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n      return p;\n    }\n\n    var m = new RegExp(\"^\" + this.regex.hsla + \"$\").exec(hsl);\n    if( m ){\n\n      // get hue\n      h = parseInt( m[1] );\n      if( h < 0 ){\n        h = ( 360 - (-1*h % 360) ) % 360;\n      } else if( h > 360 ){\n        h = h % 360;\n      }\n      h /= 360; // normalise on [0, 1]\n\n      s = parseFloat( m[2] );\n      if( s < 0 || s > 100 ){ return; } // saturation is [0, 100]\n      s = s/100; // normalise on [0, 1]\n\n      l = parseFloat( m[3] );\n      if( l < 0 || l > 100 ){ return; } // lightness is [0, 100]\n      l = l/100; // normalise on [0, 1]\n\n      a = m[4];\n      if( a !== undefined ){\n        a = parseFloat( a );\n\n        if( a < 0 || a > 1 ){ return; } // alpha is [0, 1]\n      }\n\n      // now, convert to rgb\n      // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript\n      if( s === 0 ){\n        r = g = b = Math.round(l * 255); // achromatic\n      } else {\n        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n        var p = 2 * l - q;\n        r = Math.round( 255 * hue2rgb(p, q, h + 1/3) );\n        g = Math.round( 255 * hue2rgb(p, q, h) );\n        b = Math.round( 255 * hue2rgb(p, q, h - 1/3) );\n      }\n\n      ret = [r, g, b, a];\n    }\n\n    return ret;\n  },\n\n  // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0)\n  rgb2tuple: function( rgb ){\n    var ret;\n\n    var m = new RegExp(\"^\" + this.regex.rgba + \"$\").exec(rgb);\n    if( m ){\n      ret = [];\n\n      var isPct = [];\n      for( var i = 1; i <= 3; i++ ){\n        var channel = m[i];\n\n        if( channel[ channel.length - 1 ] === \"%\" ){\n          isPct[i] = true;\n        }\n        channel = parseFloat( channel );\n\n        if( isPct[i] ){\n          channel = channel/100 * 255; // normalise to [0, 255]\n        }\n\n        if( channel < 0 || channel > 255 ){ return; } // invalid channel value\n\n        ret.push( Math.floor(channel) );\n      }\n\n      var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3];\n      var allArePct = isPct[1] && isPct[2] && isPct[3];\n      if( atLeastOneIsPct && !allArePct ){ return; } // must all be percent values if one is\n\n      var alpha = m[4];\n      if( alpha !== undefined ){\n        alpha = parseFloat( alpha );\n\n        if( alpha < 0 || alpha > 1 ){ return; } // invalid alpha value\n\n        ret.push( alpha );\n      }\n    }\n\n    return ret;\n  },\n\n  colorname2tuple: function( color ){\n    return this.colors[ color.toLowerCase() ];\n  },\n\n  color2tuple: function( color ){\n    return ( is.array(color) ? color : null )\n      || this.colorname2tuple(color)\n      || this.hex2tuple(color)\n      || this.rgb2tuple(color)\n      || this.hsl2tuple(color);\n  },\n\n  colors: {\n    // special colour names\n    transparent: [0, 0, 0, 0], // NB alpha === 0\n\n    // regular colours\n    aliceblue: [240, 248, 255],\n    antiquewhite: [250, 235, 215],\n    aqua: [0, 255, 255],\n    aquamarine: [127, 255, 212],\n    azure: [240, 255, 255],\n    beige: [245, 245, 220],\n    bisque: [255, 228, 196],\n    black: [0, 0, 0],\n    blanchedalmond: [255, 235, 205],\n    blue: [0, 0, 255],\n    blueviolet: [138, 43, 226],\n    brown: [165, 42, 42],\n    burlywood: [222, 184, 135],\n    cadetblue: [95, 158, 160],\n    chartreuse: [127, 255, 0],\n    chocolate: [210, 105, 30],\n    coral: [255, 127, 80],\n    cornflowerblue: [100, 149, 237],\n    cornsilk: [255, 248, 220],\n    crimson: [220, 20, 60],\n    cyan: [0, 255, 255],\n    darkblue: [0, 0, 139],\n    darkcyan: [0, 139, 139],\n    darkgoldenrod: [184, 134, 11],\n    darkgray: [169, 169, 169],\n    darkgreen: [0, 100, 0],\n    darkgrey: [169, 169, 169],\n    darkkhaki: [189, 183, 107],\n    darkmagenta: [139, 0, 139],\n    darkolivegreen: [85, 107, 47],\n    darkorange: [255, 140, 0],\n    darkorchid: [153, 50, 204],\n    darkred: [139, 0, 0],\n    darksalmon: [233, 150, 122],\n    darkseagreen: [143, 188, 143],\n    darkslateblue: [72, 61, 139],\n    darkslategray: [47, 79, 79],\n    darkslategrey: [47, 79, 79],\n    darkturquoise: [0, 206, 209],\n    darkviolet: [148, 0, 211],\n    deeppink: [255, 20, 147],\n    deepskyblue: [0, 191, 255],\n    dimgray: [105, 105, 105],\n    dimgrey: [105, 105, 105],\n    dodgerblue: [30, 144, 255],\n    firebrick: [178, 34, 34],\n    floralwhite: [255, 250, 240],\n    forestgreen: [34, 139, 34],\n    fuchsia: [255, 0, 255],\n    gainsboro: [220, 220, 220],\n    ghostwhite: [248, 248, 255],\n    gold: [255, 215, 0],\n    goldenrod: [218, 165, 32],\n    gray: [128, 128, 128],\n    grey: [128, 128, 128],\n    green: [0, 128, 0],\n    greenyellow: [173, 255, 47],\n    honeydew: [240, 255, 240],\n    hotpink: [255, 105, 180],\n    indianred: [205, 92, 92],\n    indigo: [75, 0, 130],\n    ivory: [255, 255, 240],\n    khaki: [240, 230, 140],\n    lavender: [230, 230, 250],\n    lavenderblush: [255, 240, 245],\n    lawngreen: [124, 252, 0],\n    lemonchiffon: [255, 250, 205],\n    lightblue: [173, 216, 230],\n    lightcoral: [240, 128, 128],\n    lightcyan: [224, 255, 255],\n    lightgoldenrodyellow: [250, 250, 210],\n    lightgray: [211, 211, 211],\n    lightgreen: [144, 238, 144],\n    lightgrey: [211, 211, 211],\n    lightpink: [255, 182, 193],\n    lightsalmon: [255, 160, 122],\n    lightseagreen: [32, 178, 170],\n    lightskyblue: [135, 206, 250],\n    lightslategray: [119, 136, 153],\n    lightslategrey: [119, 136, 153],\n    lightsteelblue: [176, 196, 222],\n    lightyellow: [255, 255, 224],\n    lime: [0, 255, 0],\n    limegreen: [50, 205, 50],\n    linen: [250, 240, 230],\n    magenta: [255, 0, 255],\n    maroon: [128, 0, 0],\n    mediumaquamarine: [102, 205, 170],\n    mediumblue: [0, 0, 205],\n    mediumorchid: [186, 85, 211],\n    mediumpurple: [147, 112, 219],\n    mediumseagreen: [60, 179, 113],\n    mediumslateblue: [123, 104, 238],\n    mediumspringgreen: [0, 250, 154],\n    mediumturquoise: [72, 209, 204],\n    mediumvioletred: [199, 21, 133],\n    midnightblue: [25, 25, 112],\n    mintcream: [245, 255, 250],\n    mistyrose: [255, 228, 225],\n    moccasin: [255, 228, 181],\n    navajowhite: [255, 222, 173],\n    navy: [0, 0, 128],\n    oldlace: [253, 245, 230],\n    olive: [128, 128, 0],\n    olivedrab: [107, 142, 35],\n    orange: [255, 165, 0],\n    orangered: [255, 69, 0],\n    orchid: [218, 112, 214],\n    palegoldenrod: [238, 232, 170],\n    palegreen: [152, 251, 152],\n    paleturquoise: [175, 238, 238],\n    palevioletred: [219, 112, 147],\n    papayawhip: [255, 239, 213],\n    peachpuff: [255, 218, 185],\n    peru: [205, 133, 63],\n    pink: [255, 192, 203],\n    plum: [221, 160, 221],\n    powderblue: [176, 224, 230],\n    purple: [128, 0, 128],\n    red: [255, 0, 0],\n    rosybrown: [188, 143, 143],\n    royalblue: [65, 105, 225],\n    saddlebrown: [139, 69, 19],\n    salmon: [250, 128, 114],\n    sandybrown: [244, 164, 96],\n    seagreen: [46, 139, 87],\n    seashell: [255, 245, 238],\n    sienna: [160, 82, 45],\n    silver: [192, 192, 192],\n    skyblue: [135, 206, 235],\n    slateblue: [106, 90, 205],\n    slategray: [112, 128, 144],\n    slategrey: [112, 128, 144],\n    snow: [255, 250, 250],\n    springgreen: [0, 255, 127],\n    steelblue: [70, 130, 180],\n    tan: [210, 180, 140],\n    teal: [0, 128, 128],\n    thistle: [216, 191, 216],\n    tomato: [255, 99, 71],\n    turquoise: [64, 224, 208],\n    violet: [238, 130, 238],\n    wheat: [245, 222, 179],\n    white: [255, 255, 255],\n    whitesmoke: [245, 245, 245],\n    yellow: [255, 255, 0],\n    yellowgreen: [154, 205, 50]\n  }\n};\n\n},{\"../is\":77}],94:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\nvar math = _dereq_('../math');\n\nvar util = {\n\n  falsify: function(){ return false; },\n\n  zeroify: function(){ return 0; },\n\n  noop: function(){},\n\n  /* jshint ignore:start */\n  error: function( msg ){\n    if( console.error ){\n      console.error.apply( console, arguments );\n\n      if( console.trace ){ console.trace(); }\n    } else {\n      console.log.apply( console, arguments );\n\n      if( console.trace ){ console.trace(); }\n    }\n  },\n  /* jshint ignore:end */\n\n  clone: function( obj ){\n    return this.extend( {}, obj );\n  },\n\n  // gets a shallow copy of the argument\n  copy: function( obj ){\n    if( obj == null ){\n      return obj;\n    } if( is.array(obj) ){\n      return obj.slice();\n    } else if( is.plainObject(obj) ){\n      return this.clone( obj );\n    } else {\n      return obj;\n    }\n  }\n\n};\n\nutil.makeBoundingBox = math.makeBoundingBox.bind( math );\n\nutil._staticEmptyObject = {};\n\nutil.staticEmptyObject = function(){\n  return util._staticEmptyObject;\n};\n\nutil.extend = Object.assign != null ? Object.assign : function( tgt ){\n  var args = arguments;\n\n  for( var i = 1; i < args.length; i++ ){\n    var obj = args[i];\n\n    for( var k in obj ){\n      tgt[k] = obj[k];\n    }\n  }\n\n  return tgt;\n};\n\n[\n  _dereq_('./colors'),\n  _dereq_('./maps'),\n  { memoize: _dereq_('./memoize') },\n  _dereq_('./regex'),\n  _dereq_('./strings'),\n  _dereq_('./timing')\n].forEach(function( req ){\n  util.extend( util, req );\n});\n\nmodule.exports = util;\n\n},{\"../is\":77,\"../math\":79,\"./colors\":93,\"./maps\":95,\"./memoize\":96,\"./regex\":97,\"./strings\":98,\"./timing\":99}],95:[function(_dereq_,module,exports){\n'use strict';\n\nvar is = _dereq_('../is');\n\nmodule.exports = {\n  // has anything been set in the map\n  mapEmpty: function( map ){\n    var empty = true;\n\n    if( map != null ){\n      for(var i in map){ // jshint ignore:line\n        empty = false;\n        break;\n      }\n    }\n\n    return empty;\n  },\n\n  // pushes to the array at the end of a map (map may not be built)\n  pushMap: function( options ){\n    var array = this.getMap(options);\n\n    if( array == null ){ // if empty, put initial array\n      this.setMap( this.extend({}, options, {\n        value: [ options.value ]\n      }) );\n    } else {\n      array.push( options.value );\n    }\n  },\n\n  // sets the value in a map (map may not be built)\n  setMap: function( options ){\n    var obj = options.map;\n    var key;\n    var keys = options.keys;\n    var l = keys.length;\n\n    for(var i = 0; i < l; i++){\n      var key = keys[i];\n\n      if( is.plainObject( key ) ){\n        this.error('Tried to set map with object key');\n      }\n\n      if( i < keys.length - 1 ){\n\n        // extend the map if necessary\n        if( obj[key] == null ){\n          obj[key] = {};\n        }\n\n        obj = obj[key];\n      } else {\n        // set the value\n        obj[key] = options.value;\n      }\n    }\n  },\n\n  // gets the value in a map even if it's not built in places\n  getMap: function( options ){\n    var obj = options.map;\n    var keys = options.keys;\n    var l = keys.length;\n\n    for(var i = 0; i < l; i++){\n      var key = keys[i];\n\n      if( is.plainObject( key ) ){\n        this.error('Tried to get map with object key');\n      }\n\n      obj = obj[key];\n\n      if( obj == null ){\n        return obj;\n      }\n    }\n\n    return obj;\n  },\n\n  // deletes the entry in the map\n  deleteMap: function( options ){\n    var obj = options.map;\n    var keys = options.keys;\n    var l = keys.length;\n    var keepChildren = options.keepChildren;\n\n    for(var i = 0; i < l; i++){\n      var key = keys[i];\n\n      if( is.plainObject( key ) ){\n        this.error('Tried to delete map with object key');\n      }\n\n      var lastKey = i === options.keys.length - 1;\n      if( lastKey ){\n\n        if( keepChildren ){ // then only delete child fields not in keepChildren\n          for( var child in obj ){\n            if( !keepChildren[child] ){\n              obj[child] = undefined;\n            }\n          }\n        } else {\n          obj[key] = undefined;\n        }\n\n      } else {\n        obj = obj[key];\n      }\n    }\n  }\n};\n\n},{\"../is\":77}],96:[function(_dereq_,module,exports){\n'use strict';\n\nmodule.exports = function memoize( fn, keyFn ){\n  var self = this;\n  var cache = {};\n\n  if( !keyFn ){\n    keyFn = function(){\n      if( arguments.length === 1 ){\n        return arguments[0];\n      }\n\n      var args = [];\n\n      for( var i = 0; i < arguments.length; i++ ){\n        args.push( arguments[i] );\n      }\n\n      return args.join('$');\n    };\n  }\n\n  return function memoizedFn(){\n    var args = arguments;\n    var ret;\n    var k = keyFn.apply( self, args );\n\n    if( !(ret = cache[k]) ){\n      ret = cache[k] = fn.apply( self, args );\n    }\n\n    return ret;\n  };\n};\n\n},{}],97:[function(_dereq_,module,exports){\n'use strict';\n\nvar number = \"(?:[-+]?(?:(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[Ee][+-]?\\\\d+)?))\";\n\nvar rgba = \"rgb[a]?\\\\((\"+ number +\"[%]?)\\\\s*,\\\\s*(\"+ number +\"[%]?)\\\\s*,\\\\s*(\"+ number +\"[%]?)(?:\\\\s*,\\\\s*(\"+ number +\"))?\\\\)\";\nvar rgbaNoBackRefs = \"rgb[a]?\\\\((?:\"+ number +\"[%]?)\\\\s*,\\\\s*(?:\"+ number +\"[%]?)\\\\s*,\\\\s*(?:\"+ number +\"[%]?)(?:\\\\s*,\\\\s*(?:\"+ number +\"))?\\\\)\";\n\nvar hsla = \"hsl[a]?\\\\((\"+ number +\")\\\\s*,\\\\s*(\"+ number +\"[%])\\\\s*,\\\\s*(\"+ number +\"[%])(?:\\\\s*,\\\\s*(\"+ number +\"))?\\\\)\";\nvar hslaNoBackRefs = \"hsl[a]?\\\\((?:\"+ number +\")\\\\s*,\\\\s*(?:\"+ number +\"[%])\\\\s*,\\\\s*(?:\"+ number +\"[%])(?:\\\\s*,\\\\s*(?:\"+ number +\"))?\\\\)\";\n\nvar hex3 = \"\\\\#[0-9a-fA-F]{3}\";\nvar hex6 = \"\\\\#[0-9a-fA-F]{6}\";\n\nmodule.exports = {\n  regex: {\n    number: number,\n    rgba: rgba,\n    rgbaNoBackRefs: rgbaNoBackRefs,\n    hsla: hsla,\n    hslaNoBackRefs: hslaNoBackRefs,\n    hex3: hex3,\n    hex6: hex6\n  }\n};\n\n},{}],98:[function(_dereq_,module,exports){\n'use strict';\n\nvar memoize = _dereq_('./memoize');\nvar is = _dereq_('../is');\n\nmodule.exports = {\n\n  camel2dash: memoize( function( str ){\n    return str.replace(/([A-Z])/g, function( v ){\n      return '-' + v.toLowerCase();\n    });\n  } ),\n\n  dash2camel: memoize( function( str ){\n    return str.replace(/(-\\w)/g, function( v ){\n      return v[1].toUpperCase();\n    });\n  } ),\n\n  capitalize: function(str){\n    if( is.emptyString(str) ){\n      return str;\n    }\n\n    return str.charAt(0).toUpperCase() + str.substring(1);\n  }\n\n};\n\n},{\"../is\":77,\"./memoize\":96}],99:[function(_dereq_,module,exports){\n'use strict';\n\nvar window = _dereq_('../window');\nvar is = _dereq_('../is');\nvar performance = window ? window.performance : null;\n\nvar util = {};\n\nvar raf = !window ? null : ( window.requestAnimationFrame || window.mozRequestAnimationFrame ||\n      window.webkitRequestAnimationFrame || window.msRequestAnimationFrame );\n\nraf = raf || function( fn ){\n  if( fn ){\n    setTimeout(function(){\n      fn( pnow() );\n    }, 1000/60);\n  }\n};\n\nutil.requestAnimationFrame = function(fn){\n  raf( fn );\n};\n\nvar pnow = performance && performance.now ? function(){ return performance.now(); } : function(){ return Date.now(); };\n\nutil.performanceNow = pnow;\n\n// ported lodash throttle function\nutil.throttle = function(func, wait, options) {\n  var leading = true,\n      trailing = true;\n\n  if (options === false) {\n    leading = false;\n  } else if (is.plainObject(options)) {\n    leading = 'leading' in options ? options.leading : leading;\n    trailing = 'trailing' in options ? options.trailing : trailing;\n  }\n  options = options || {};\n  options.leading = leading;\n  options.maxWait = wait;\n  options.trailing = trailing;\n\n  return util.debounce(func, wait, options);\n};\n\nutil.now = function(){\n  return Date.now();\n};\n\nutil.debounce = function(func, wait, options) { // ported lodash debounce function\n  var util = this;\n  var args,\n      maxTimeoutId,\n      result,\n      stamp,\n      thisArg,\n      timeoutId,\n      trailingCall,\n      lastCalled = 0,\n      maxWait = false,\n      trailing = true;\n\n  if (!is.fn(func)) {\n    return;\n  }\n  wait = Math.max(0, wait) || 0;\n  if (options === true) {\n    var leading = true;\n    trailing = false;\n  } else if (is.plainObject(options)) {\n    leading = options.leading;\n    maxWait = 'maxWait' in options && (Math.max(wait, options.maxWait) || 0);\n    trailing = 'trailing' in options ? options.trailing : trailing;\n  }\n  var delayed = function() {\n    var remaining = wait - (util.now() - stamp);\n    if (remaining <= 0) {\n      if (maxTimeoutId) {\n        clearTimeout(maxTimeoutId);\n      }\n      var isCalled = trailingCall;\n      maxTimeoutId = timeoutId = trailingCall = undefined;\n      if (isCalled) {\n        lastCalled = util.now();\n        result = func.apply(thisArg, args);\n        if (!timeoutId && !maxTimeoutId) {\n          args = thisArg = null;\n        }\n      }\n    } else {\n      timeoutId = setTimeout(delayed, remaining);\n    }\n  };\n\n  var maxDelayed = function() {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n    maxTimeoutId = timeoutId = trailingCall = undefined;\n    if (trailing || (maxWait !== wait)) {\n      lastCalled = util.now();\n      result = func.apply(thisArg, args);\n      if (!timeoutId && !maxTimeoutId) {\n        args = thisArg = null;\n      }\n    }\n  };\n\n  return function() {\n    args = arguments;\n    stamp = util.now();\n    thisArg = this;\n    trailingCall = trailing && (timeoutId || !leading);\n\n    if (maxWait === false) {\n      var leadingCall = leading && !timeoutId;\n    } else {\n      if (!maxTimeoutId && !leading) {\n        lastCalled = stamp;\n      }\n      var remaining = maxWait - (stamp - lastCalled),\n          isCalled = remaining <= 0;\n\n      if (isCalled) {\n        if (maxTimeoutId) {\n          maxTimeoutId = clearTimeout(maxTimeoutId);\n        }\n        lastCalled = stamp;\n        result = func.apply(thisArg, args);\n      }\n      else if (!maxTimeoutId) {\n        maxTimeoutId = setTimeout(maxDelayed, remaining);\n      }\n    }\n    if (isCalled && timeoutId) {\n      timeoutId = clearTimeout(timeoutId);\n    }\n    else if (!timeoutId && wait !== maxWait) {\n      timeoutId = setTimeout(delayed, wait);\n    }\n    if (leadingCall) {\n      isCalled = true;\n      result = func.apply(thisArg, args);\n    }\n    if (isCalled && !timeoutId && !maxTimeoutId) {\n      args = thisArg = null;\n    }\n    return result;\n  };\n};\n\nmodule.exports = util;\n\n},{\"../is\":77,\"../window\":100}],100:[function(_dereq_,module,exports){\nmodule.exports = ( typeof window === 'undefined' ? null : window );\n\n},{}]},{},[76])(76)\n});\n\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n  // Implemented from pseudocode from wikipedia\n  aStar: function(options) {\n    var eles = this;\n\n    options = options || {};\n\n    // Reconstructs the path from Start to End, acumulating the result in pathAcum\n    var reconstructPath = function(start, end, cameFromMap, pathAcum) {\n      // Base case\n      if (start == end) {\n        pathAcum.push( cy.getElementById(end) );\n        return pathAcum;\n      }\n\n      if (end in cameFromMap) {\n        // We know which node is before the last one\n        var previous = cameFromMap[end];\n        var previousEdge = cameFromEdge[end];\n\n        pathAcum.push( cy.getElementById(end) );\n        pathAcum.push( cy.getElementById(previousEdge) );\n\n\n        return reconstructPath(start,\n                     previous,\n                     cameFromMap,\n                     pathAcum);\n      }\n\n      // We should not reach here!\n      return undefined;\n    };\n\n    // Returns the index of the element in openSet which has minimum fScore\n    var findMin = function(openSet, fScore) {\n      if (openSet.length === 0) {\n        // Should never be the case\n        return undefined;\n      }\n      var minPos = 0;\n      var tempScore = fScore[openSet[0]];\n      for (var i = 1; i < openSet.length; i++) {\n        var s = fScore[openSet[i]];\n        if (s < tempScore) {\n          tempScore = s;\n          minPos = i;\n        }\n      }\n      return minPos;\n    };\n\n    var cy = this._private.cy;\n\n    // root - mandatory!\n    if (options != null && options.root != null) {\n      var source = is.string(options.root) ?\n        // use it as a selector, e.g. \"#rootID\n        this.filter(options.root)[0] :\n        options.root[0];\n    } else {\n      return undefined;\n    }\n\n    // goal - mandatory!\n    if (options.goal != null) {\n      var target = is.string(options.goal) ?\n        // use it as a selector, e.g. \"#goalID\n        this.filter(options.goal)[0] :\n        options.goal[0];\n    } else {\n      return undefined;\n    }\n\n    // Heuristic function - optional\n    if (options.heuristic != null && is.fn(options.heuristic)) {\n      var heuristic = options.heuristic;\n    } else {\n      var heuristic = function(){ return 0; }; // use constant if unspecified\n    }\n\n    // Weight function - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var closedSet = [];\n    var openSet = [source.id()];\n    var cameFrom = {};\n    var cameFromEdge = {};\n    var gScore = {};\n    var fScore = {};\n\n    gScore[source.id()] = 0;\n    fScore[source.id()] = heuristic(source);\n\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n\n    // Counter\n    var steps = 0;\n\n    // Main loop\n    while (openSet.length > 0) {\n      var minPos = findMin(openSet, fScore);\n      var cMin = cy.getElementById( openSet[minPos] );\n      steps++;\n\n      // If we've found our goal, then we are done\n      if (cMin.id() == target.id()) {\n        var rPath = reconstructPath(source.id(), target.id(), cameFrom, []);\n        rPath.reverse();\n        return {\n          found : true,\n          distance : gScore[cMin.id()],\n          path : eles.spawn(rPath),\n          steps : steps\n        };\n      }\n\n      // Add cMin to processed nodes\n      closedSet.push(cMin.id());\n      // Remove cMin from boundary nodes\n      openSet.splice(minPos, 1);\n\n      // Update scores for neighbors of cMin\n      // Take into account if graph is directed or not\n      var vwEdges = cMin.connectedEdges();\n      if( directed ){ vwEdges = vwEdges.stdFilter(function(ele){ return ele.data('source') === cMin.id(); }); }\n      vwEdges = vwEdges.intersect(edges);\n\n      for (var i = 0; i < vwEdges.length; i++) {\n        var e = vwEdges[i];\n        var w = e.connectedNodes().stdFilter(function(n){ return n.id() !== cMin.id(); }).intersect(nodes);\n\n        // if node is in closedSet, ignore it\n        if (closedSet.indexOf(w.id()) != -1) {\n          continue;\n        }\n\n        // New tentative score for node w\n        var tempScore = gScore[cMin.id()] + weightFn.apply(e, [e]);\n\n        // Update gScore for node w if:\n        //   w not present in openSet\n        // OR\n        //   tentative gScore is less than previous value\n\n        // w not in openSet\n        if (openSet.indexOf(w.id()) == -1) {\n          gScore[w.id()] = tempScore;\n          fScore[w.id()] = tempScore + heuristic(w);\n          openSet.push(w.id()); // Add node to openSet\n          cameFrom[w.id()] = cMin.id();\n          cameFromEdge[w.id()] = e.id();\n          continue;\n        }\n        // w already in openSet, but with greater gScore\n        if (tempScore < gScore[w.id()]) {\n          gScore[w.id()] = tempScore;\n          fScore[w.id()] = tempScore + heuristic(w);\n          cameFrom[w.id()] = cMin.id();\n        }\n\n      } // End of neighbors update\n\n    } // End of main loop\n\n    // If we've reached here, then we've not reached our goal\n    return {\n      found : false,\n      distance : undefined,\n      path : undefined,\n      steps : steps\n    };\n  }\n\n}); // elesfn\n\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\nvar util = require('../../util');\n\nvar elesfn = ({\n\n  // Implemented from pseudocode from wikipedia\n  bellmanFord: function(options) {\n    var eles = this;\n\n    options = options || {};\n\n    // Weight function - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    // root - mandatory!\n    if (options.root != null) {\n      if (is.string(options.root)) {\n        // use it as a selector, e.g. \"#rootID\n        var source = this.filter(options.root)[0];\n      } else {\n        var source = options.root[0];\n      }\n    } else {\n      return undefined;\n    }\n\n    var cy = this._private.cy;\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n\n    // mapping: node id -> position in nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Initializations\n    var cost = [];\n    var predecessor = [];\n    var predEdge = [];\n\n    for (var i = 0; i < numNodes; i++) {\n      if (nodes[i].id() === source.id()) {\n        cost[i] = 0;\n      } else {\n        cost[i] = Infinity;\n      }\n      predecessor[i] = undefined;\n    }\n\n    // Edges relaxation\n    var flag = false;\n    for (var i = 1; i < numNodes; i++) {\n      flag = false;\n      for (var e = 0; e < edges.length; e++) {\n        var sourceIndex = id2position[edges[e].source().id()];\n        var targetIndex = id2position[edges[e].target().id()];\n        var weight = weightFn.apply(edges[e], [edges[e]]);\n\n        var temp = cost[sourceIndex] + weight;\n        if (temp < cost[targetIndex]) {\n          cost[targetIndex] = temp;\n          predecessor[targetIndex] = sourceIndex;\n          predEdge[targetIndex] = edges[e];\n          flag = true;\n        }\n\n        // If undirected graph, we need to take into account the 'reverse' edge\n        if (!directed) {\n          var temp = cost[targetIndex] + weight;\n          if (temp < cost[sourceIndex]) {\n            cost[sourceIndex] = temp;\n            predecessor[sourceIndex] = targetIndex;\n            predEdge[sourceIndex] = edges[e];\n            flag = true;\n          }\n        }\n      }\n\n      if (!flag) {\n        break;\n      }\n    }\n\n    if (flag) {\n      // Check for negative weight cycles\n      for (var e = 0; e < edges.length; e++) {\n        var sourceIndex = id2position[edges[e].source().id()];\n        var targetIndex = id2position[edges[e].target().id()];\n        var weight = weightFn.apply(edges[e], [edges[e]]);\n\n        if (cost[sourceIndex] + weight < cost[targetIndex]) {\n          util.error(\"Graph contains a negative weight cycle for Bellman-Ford\");\n          return { pathTo: undefined,\n               distanceTo: undefined,\n               hasNegativeWeightCycle: true};\n        }\n      }\n    }\n\n    // Build result object\n    var position2id = [];\n    for (var i = 0; i < numNodes; i++) {\n      position2id.push(nodes[i].id());\n    }\n\n\n    var res = {\n      distanceTo : function(to) {\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n\n        return cost[id2position[toId]];\n      },\n\n      pathTo : function(to) {\n\n        var reconstructPathAux = function(predecessor, fromPos, toPos, position2id, acumPath, predEdge) {\n          for(;;){\n            // Add toId to path\n            acumPath.push( cy.getElementById(position2id[toPos]) );\n            acumPath.push( predEdge[toPos] );\n\n            if (fromPos === toPos) {\n              // reached starting node\n              return acumPath;\n            }\n\n            // If no path exists, discart acumulated path and return undefined\n            var predPos = predecessor[toPos];\n            if (typeof predPos === \"undefined\") {\n              return undefined;\n            }\n\n            toPos = predPos;\n          }\n\n        };\n\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n        var path = [];\n\n        // This returns a reversed path\n        var res =  reconstructPathAux(predecessor,\n                      id2position[source.id()],\n                      id2position[toId],\n                      position2id,\n                      path,\n                      predEdge);\n\n        // Get it in the correct order and return it\n        if (res != null) {\n          res.reverse();\n        }\n\n        return eles.spawn(res);\n      },\n\n      hasNegativeWeightCycle: false\n    };\n\n    return res;\n\n  } // bellmanFord\n\n}); // elesfn\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n  // Implemented from the algorithm in the paper \"On Variants of Shortest-Path Betweenness Centrality and their Generic Computation\" by Ulrik Brandes\n  betweennessCentrality: function (options) {\n    options = options || {};\n\n    // Weight - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n      var weighted = true;\n    } else {\n      var weighted = false;\n    }\n\n    // Directed - default false\n    if (options.directed != null && is.bool(options.directed)) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var priorityInsert = function (queue, ele) {\n      queue.unshift(ele);\n      for (var i = 0; d[queue[i]] < d[queue[i + 1]] && i < queue.length - 1; i++) {\n        var tmp = queue[i];\n        queue[i] = queue[i + 1];\n        queue[i + 1] = tmp;\n      }\n    };\n\n    var cy = this._private.cy;\n\n    // starting\n    var V = this.nodes();\n    var A = {};\n    var C = {};\n\n    // A contains the neighborhoods of every node\n    for (var i = 0; i < V.length; i++) {\n      if (directed) {\n        A[V[i].id()] = V[i].outgoers(\"node\"); // get outgoers of every node\n      } else {\n        A[V[i].id()] = V[i].openNeighborhood(\"node\"); // get neighbors of every node\n      }\n    }\n\n    // C contains the betweenness values\n    for (var i = 0; i < V.length; i++) {\n      C[V[i].id()] = 0;\n    }\n\n    for (var s = 0; s < V.length; s++) {\n      var S = []; // stack\n      var P = {};\n      var g = {};\n      var d = {};\n      var Q = []; // queue\n\n      // init dictionaries\n      for (var i = 0; i < V.length; i++) {\n        P[V[i].id()] = [];\n        g[V[i].id()] = 0;\n        d[V[i].id()] = Number.POSITIVE_INFINITY;\n      }\n\n      g[V[s].id()] = 1; // sigma\n      d[V[s].id()] = 0; // distance to s\n\n      Q.unshift(V[s].id());\n\n      while (Q.length > 0) {\n        var v = Q.pop();\n        S.push(v);\n        if (weighted) {\n          A[v].forEach(function (w) {\n            if (cy.$('#' + v).edgesTo(w).length > 0) {\n              var edge = cy.$('#' + v).edgesTo(w)[0];\n            } else {\n              var edge = w.edgesTo('#' + v)[0];\n            }\n\n            var edgeWeight = weightFn.apply(edge, [edge]);\n\n            if (d[w.id()] > d[v] + edgeWeight) {\n              d[w.id()] = d[v] + edgeWeight;\n              if (Q.indexOf(w.id()) < 0) { //if w is not in Q\n                priorityInsert(Q, w.id());\n              } else { // update position if w is in Q\n                Q.splice(Q.indexOf(w.id()), 1);\n                priorityInsert(Q, w.id());\n              }\n              g[w.id()] = 0;\n              P[w.id()] = [];\n            }\n            if (d[w.id()] == d[v] + edgeWeight) {\n              g[w.id()] = g[w.id()] + g[v];\n              P[w.id()].push(v);\n            }\n          });\n        } else {\n          A[v].forEach(function (w) {\n            if (d[w.id()] == Number.POSITIVE_INFINITY) {\n              Q.unshift(w.id());\n              d[w.id()] = d[v] + 1;\n            }\n            if (d[w.id()] == d[v] + 1) {\n              g[w.id()] = g[w.id()] + g[v];\n              P[w.id()].push(v);\n            }\n          });\n        }\n      }\n\n      var e = {};\n      for (var i = 0; i < V.length; i++) {\n        e[V[i].id()] = 0;\n      }\n\n      while (S.length > 0) {\n        var w = S.pop();\n        P[w].forEach(function (v) {\n          e[v] = e[v] + (g[v] / g[w]) * (1 + e[w]);\n          if (w != V[s].id())\n            C[w] = C[w] + e[w];\n        });\n      }\n    }\n\n    var max = 0;\n    for (var key in C) {\n      if (max < C[key])\n        max = C[key];\n    }\n\n    var ret = {\n      betweenness: function (node) {\n        if (is.string(node)) {\n          var node = (cy.filter(node)[0]).id();\n        } else {\n          var node = node.id();\n        }\n\n        return C[node];\n      },\n\n      betweennessNormalized: function (node) {\n        if (is.string(node)) {\n          var node = (cy.filter(node)[0]).id();\n        } else {\n          var node = node.id();\n        }\n\n        return C[node] / max;\n      }\n    };\n\n    // alias\n    ret.betweennessNormalised = ret.betweennessNormalized;\n\n    return ret;\n  } // betweennessCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.bc = elesfn.betweennessCentrality;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\nvar Heap = require('../../heap');\n\nvar defineSearch = function( params ){\n  params = {\n    bfs: params.bfs || !params.dfs,\n    dfs: params.dfs || !params.bfs\n  };\n\n  // from pseudocode on wikipedia\n  return function searchFn( roots, fn, directed ){\n    var options;\n    var std;\n    var thisArg;\n    if( is.plainObject(roots) && !is.elementOrCollection(roots) ){\n      options = roots;\n      roots = options.roots || options.root;\n      fn = options.visit;\n      directed = options.directed;\n      std = options.std;\n      thisArg = options.thisArg;\n    }\n\n    directed = arguments.length === 2 && !is.fn(fn) ? fn : directed;\n    fn = is.fn(fn) ? fn : function(){};\n\n    var cy = this._private.cy;\n    var v = roots = is.string(roots) ? this.filter(roots) : roots;\n    var Q = [];\n    var connectedNodes = [];\n    var connectedBy = {};\n    var id2depth = {};\n    var V = {};\n    var j = 0;\n    var found;\n    var nodes = this.nodes();\n    var edges = this.edges();\n\n    // enqueue v\n    for( var i = 0; i < v.length; i++ ){\n      if( v[i].isNode() ){\n        Q.unshift( v[i] );\n\n        if( params.bfs ){\n          V[ v[i].id() ] = true;\n\n          connectedNodes.push( v[i] );\n        }\n\n        id2depth[ v[i].id() ] = 0;\n      }\n    }\n\n    while( Q.length !== 0 ){\n      var v = params.bfs ? Q.shift() : Q.pop();\n\n      if( params.dfs ){\n        if( V[ v.id() ] ){ continue; }\n\n        V[ v.id() ] = true;\n\n        connectedNodes.push( v );\n      }\n\n      var depth = id2depth[ v.id() ];\n      var prevEdge = connectedBy[ v.id() ];\n      var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not( v )[0];\n      var ret;\n\n      if( std ){\n        ret = fn.call(thisArg, v, prevEdge, prevNode, j++, depth);\n      } else {\n        ret = fn.call(v, j++, depth, v, prevEdge, prevNode);\n      }\n\n      if( ret === true ){\n        found = v;\n        break;\n      }\n\n      if( ret === false ){\n        break;\n      }\n\n      var vwEdges = v.connectedEdges(directed ? function(){ return this.data('source') === v.id(); } : undefined).intersect( edges );\n      for( var i = 0; i < vwEdges.length; i++ ){\n        var e = vwEdges[i];\n        var w = e.connectedNodes(function(){ return this.id() !== v.id(); }).intersect( nodes );\n\n        if( w.length !== 0 && !V[ w.id() ] ){\n          w = w[0];\n\n          Q.push( w );\n\n          if( params.bfs ){\n            V[ w.id() ] = true;\n\n            connectedNodes.push( w );\n          }\n\n          connectedBy[ w.id() ] = e;\n\n          id2depth[ w.id() ] = id2depth[ v.id() ] + 1;\n        }\n      }\n\n    }\n\n    var connectedEles = [];\n\n    for( var i = 0; i < connectedNodes.length; i++ ){\n      var node = connectedNodes[i];\n      var edge = connectedBy[ node.id() ];\n\n      if( edge ){\n        connectedEles.push( edge );\n      }\n\n      connectedEles.push( node );\n    }\n\n    return {\n      path: cy.collection( connectedEles, { unique: true } ),\n      found: cy.collection( found )\n    };\n  };\n};\n\n// search, spanning trees, etc\nvar elesfn = ({\n\n  breadthFirstSearch: defineSearch({ bfs: true }),\n  depthFirstSearch: defineSearch({ dfs: true }),\n\n  // kruskal's algorithm (finds min spanning tree, assuming undirected graph)\n  // implemented from pseudocode from wikipedia\n  kruskal: function( weightFn ){\n    var cy = this.cy();\n\n    weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)\n\n    function findSet(ele){\n      for( var i = 0; i < forest.length; i++ ){\n        var eles = forest[i];\n\n        if( eles.anySame(ele) ){\n          return {\n            eles: eles,\n            index: i\n          };\n        }\n      }\n    }\n\n    var A = cy.collection(cy, []);\n    var forest = [];\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){\n      forest.push( nodes[i].collection() );\n    }\n\n    var edges = this.edges();\n    var S = edges.toArray().sort(function(a, b){\n      var weightA = weightFn.call(a, a);\n      var weightB = weightFn.call(b, b);\n\n      return weightA - weightB;\n    });\n\n    for(var i = 0; i < S.length; i++){\n      var edge = S[i];\n      var u = edge.source()[0];\n      var v = edge.target()[0];\n      var setU = findSet(u);\n      var setV = findSet(v);\n\n      if( setU.index !== setV.index ){\n        A = A.add( edge );\n\n        // combine forests for u and v\n        forest[ setU.index ] = setU.eles.add( setV.eles );\n        forest.splice( setV.index, 1 );\n      }\n    }\n\n    return nodes.add( A );\n\n  },\n\n  dijkstra: function( root, weightFn, directed ){\n    var options;\n    if( is.plainObject(root) && !is.elementOrCollection(root) ){\n      options = root;\n      root = options.root;\n      weightFn = options.weight;\n      directed = options.directed;\n    }\n\n    var cy = this._private.cy;\n    weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)\n\n    var source = is.string(root) ? this.filter(root)[0] : root[0];\n    var dist = {};\n    var prev = {};\n    var knownDist = {};\n\n    var edges = this.edges().filter(function(){ return !this.isLoop(); });\n    var nodes = this.nodes();\n\n    var getDist = function(node){\n      return dist[ node.id() ];\n    };\n\n    var setDist = function(node, d){\n      dist[ node.id() ] = d;\n\n      Q.updateItem( node );\n    };\n\n    var Q = new Heap(function( a, b ){\n      return getDist(a) - getDist(b);\n    });\n\n    for( var i = 0; i < nodes.length; i++ ){\n      var node = nodes[i];\n\n      dist[ node.id() ] = node.same( source ) ? 0 : Infinity;\n      Q.push( node );\n    }\n\n    var distBetween = function(u, v){\n      var uvs = ( directed ? u.edgesTo(v) : u.edgesWith(v) ).intersect(edges);\n      var smallestDistance = Infinity;\n      var smallestEdge;\n\n      for( var i = 0; i < uvs.length; i++ ){\n        var edge = uvs[i];\n        var weight = weightFn.apply( edge, [edge] );\n\n        if( weight < smallestDistance || !smallestEdge ){\n          smallestDistance = weight;\n          smallestEdge = edge;\n        }\n      }\n\n      return {\n        edge: smallestEdge,\n        dist: smallestDistance\n      };\n    };\n\n    while( Q.size() > 0 ){\n      var u = Q.pop();\n      var smalletsDist = getDist(u);\n      var uid = u.id();\n\n      knownDist[uid] = smalletsDist;\n\n      if( smalletsDist === Math.Infinite ){\n        break;\n      }\n\n      var neighbors = u.neighborhood().intersect(nodes);\n      for( var i = 0; i < neighbors.length; i++ ){\n        var v = neighbors[i];\n        var vid = v.id();\n        var vDist = distBetween(u, v);\n\n        var alt = smalletsDist + vDist.dist;\n\n        if( alt < getDist(v) ){\n          setDist(v, alt);\n\n          prev[ vid ] = {\n            node: u,\n            edge: vDist.edge\n          };\n        }\n      } // for\n    } // while\n\n    return {\n      distanceTo: function(node){\n        var target = is.string(node) ? nodes.filter(node)[0] : node[0];\n\n        return knownDist[ target.id() ];\n      },\n\n      pathTo: function(node){\n        var target = is.string(node) ? nodes.filter(node)[0] : node[0];\n        var S = [];\n        var u = target;\n\n        if( target.length > 0 ){\n          S.unshift( target );\n\n          while( prev[ u.id() ] ){\n            var p = prev[ u.id() ];\n\n            S.unshift( p.edge );\n            S.unshift( p.node );\n\n            u = p.node;\n          }\n        }\n\n        return cy.collection( S );\n      }\n    };\n  }\n});\n\n// nice, short mathemathical alias\nelesfn.bfs = elesfn.breadthFirstSearch;\nelesfn.dfs = elesfn.depthFirstSearch;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n  closenessCentralityNormalized: function (options) {\n    options = options || {};\n\n    var cy = this.cy();\n\n    var harmonic = options.harmonic;\n    if( harmonic === undefined ){\n      harmonic = true;\n    }\n\n    var closenesses = {};\n    var maxCloseness = 0;\n    var nodes = this.nodes();\n    var fw = this.floydWarshall({ weight: options.weight, directed: options.directed });\n\n    // Compute closeness for every node and find the maximum closeness\n    for(var i = 0; i < nodes.length; i++){\n      var currCloseness = 0;\n      for (var j = 0; j < nodes.length; j++) {\n        if (i != j) {\n          var d = fw.distance(nodes[i], nodes[j]);\n\n          if( harmonic ){\n            currCloseness += 1 / d;\n          } else {\n            currCloseness += d;\n          }\n        }\n      }\n\n      if( !harmonic ){\n        currCloseness = 1 / currCloseness;\n      }\n\n      if (maxCloseness < currCloseness){\n        maxCloseness = currCloseness;\n      }\n\n      closenesses[nodes[i].id()] = currCloseness;\n    }\n\n    return {\n      closeness: function (node) {\n        if (is.string(node)) {\n          // from is a selector string\n          var node = (cy.filter(node)[0]).id();\n        } else {\n          // from is a node\n          var node = node.id();\n        }\n\n        return closenesses[node] / maxCloseness;\n      }\n    };\n  },\n\n  // Implemented from pseudocode from wikipedia\n  closenessCentrality: function (options) {\n    options = options || {};\n\n    // root - mandatory!\n    if (options.root != null) {\n      if (is.string(options.root)) {\n        // use it as a selector, e.g. \"#rootID\n        var root = this.filter(options.root)[0];\n      } else {\n        var root = options.root[0];\n      }\n    } else {\n      return undefined;\n    }\n\n    // weight - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weight = options.weight;\n    } else {\n      var weight = function(){return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null && is.bool(options.directed)) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var harmonic = options.harmonic;\n    if( harmonic === undefined ){\n      harmonic = true;\n    }\n\n    // we need distance from this node to every other node\n    var dijkstra = this.dijkstra({\n      root: root,\n      weight: weight,\n      directed: directed\n    });\n    var totalDistance = 0;\n\n    var nodes = this.nodes();\n    for (var i = 0; i < nodes.length; i++){\n      if (nodes[i].id() != root.id()){\n        var d = dijkstra.distanceTo(nodes[i]);\n\n        if( harmonic ){\n          totalDistance += 1 / d;\n        } else {\n          totalDistance += d;\n        }\n      }\n    }\n\n    return harmonic ? totalDistance : 1 / totalDistance;\n  } // closenessCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.cc = elesfn.closenessCentrality;\nelesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\nvar util = require('../../util');\n\nvar elesfn = ({\n\n  degreeCentralityNormalized: function (options) {\n    options = options || {};\n\n    var cy = this.cy();\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n\n    if (!directed) {\n      var degrees = {};\n      var maxDegree = 0;\n\n      for (var i = 0; i < numNodes; i++) {\n        var node = nodes[i];\n        // add current node to the current options object and call degreeCentrality\n        var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));\n        if (maxDegree < currDegree.degree)\n          maxDegree = currDegree.degree;\n\n        degrees[node.id()] = currDegree.degree;\n      }\n\n      return {\n        degree: function (node) {\n          if (is.string(node)) {\n            // from is a selector string\n            var node = (cy.filter(node)[0]).id();\n          } else {\n            // from is a node\n            var node = node.id();\n          }\n\n          return degrees[node] / maxDegree;\n        }\n      };\n    } else {\n      var indegrees = {};\n      var outdegrees = {};\n      var maxIndegree = 0;\n      var maxOutdegree = 0;\n\n      for (var i = 0; i < numNodes; i++) {\n        var node = nodes[i];\n        // add current node to the current options object and call degreeCentrality\n        var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));\n\n        if (maxIndegree < currDegree.indegree)\n          maxIndegree = currDegree.indegree;\n\n        if (maxOutdegree < currDegree.outdegree)\n          maxOutdegree = currDegree.outdegree;\n\n        indegrees[node.id()] = currDegree.indegree;\n        outdegrees[node.id()] = currDegree.outdegree;\n      }\n\n      return {\n        indegree: function (node) {\n          if (is.string(node)) {\n            // from is a selector string\n            var node = (cy.filter(node)[0]).id();\n          } else {\n            // from is a node\n            var node = node.id();\n          }\n\n          return indegrees[node] / maxIndegree;\n        },\n        outdegree: function (node) {\n          if (is.string(node)) {\n            // from is a selector string\n            var node = (cy.filter(node)[0]).id();\n          } else {\n            // from is a node\n            var node = node.id();\n          }\n\n          return outdegrees[node] / maxOutdegree;\n        }\n\n      };\n    }\n\n  }, // degreeCentralityNormalized\n\n  // Implemented from the algorithm in Opsahl's paper\n  // \"Node centrality in weighted networks: Generalizing degree and shortest paths\"\n  // check the heading 2 \"Degree\"\n  degreeCentrality: function (options) {\n    options = options || {};\n\n    var callingEles = this;\n\n    // root - mandatory!\n    if (options != null && options.root != null) {\n      var root = is.string(options.root) ? this.filter(options.root)[0] : options.root[0];\n    } else {\n      return undefined;\n    }\n\n    // weight - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function (e) {\n        return 1;\n      };\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    // alpha - optional\n    if (options.alpha != null && is.number(options.alpha)) {\n      var alpha = options.alpha;\n    } else {\n      alpha = 0;\n    }\n\n\n    if (!directed) {\n      var connEdges = root.connectedEdges().intersection( callingEles );\n      var k = connEdges.length;\n      var s = 0;\n\n      // Now, sum edge weights\n      for (var i = 0; i < connEdges.length; i++) {\n        var edge = connEdges[i];\n        s += weightFn.apply(edge, [edge]);\n      }\n\n      return {\n        degree: Math.pow(k, 1 - alpha) * Math.pow(s, alpha)\n      };\n    } else {\n      var incoming = root.connectedEdges('edge[target = \"' + root.id() + '\"]').intersection( callingEles );\n      var outgoing = root.connectedEdges('edge[source = \"' + root.id() + '\"]').intersection( callingEles );\n      var k_in = incoming.length;\n      var k_out = outgoing.length;\n      var s_in = 0;\n      var s_out = 0;\n\n      // Now, sum incoming edge weights\n      for (var i = 0; i < incoming.length; i++) {\n        var edge = incoming[i];\n        s_in += weightFn.apply(edge, [edge]);\n      }\n\n      // Now, sum outgoing edge weights\n      for (var i = 0; i < outgoing.length; i++) {\n        var edge = outgoing[i];\n        s_out += weightFn.apply(edge, [edge]);\n      }\n\n      return {\n        indegree: Math.pow(k_in, 1 - alpha) * Math.pow(s_in, alpha),\n        outdegree: Math.pow(k_out, 1 - alpha) * Math.pow(s_out, alpha)\n      };\n    }\n  } // degreeCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.dc = elesfn.degreeCentrality;\nelesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n  // Implemented from pseudocode from wikipedia\n  floydWarshall: function(options) {\n    options = options || {};\n\n    var cy = this.cy();\n\n    // Weight function - optional\n    if (options.weight != null && is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    // directed - optional\n    if (options.directed != null) {\n      var directed = options.directed;\n    } else {\n      var directed = false;\n    }\n\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n\n    // mapping: node id -> position in nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Initialize distance matrix\n    var dist = [];\n    for (var i = 0; i < numNodes; i++) {\n      var newRow = new Array(numNodes);\n      for (var j = 0; j < numNodes; j++) {\n        if (i == j) {\n          newRow[j] = 0;\n        } else {\n          newRow[j] = Infinity;\n        }\n      }\n      dist.push(newRow);\n    }\n\n    // Initialize matrix used for path reconstruction\n    // Initialize distance matrix\n    var next = [];\n    var edgeNext = [];\n\n    var initMatrix = function(next){\n      for (var i = 0; i < numNodes; i++) {\n        var newRow = new Array(numNodes);\n        for (var j = 0; j < numNodes; j++) {\n          newRow[j] = undefined;\n        }\n        next.push(newRow);\n      }\n    };\n\n    initMatrix(next);\n    initMatrix(edgeNext);\n\n    // Process edges\n    for (var i = 0; i < edges.length ; i++) {\n      var sourceIndex = id2position[edges[i].source().id()];\n      var targetIndex = id2position[edges[i].target().id()];\n      var weight = weightFn.apply(edges[i], [edges[i]]);\n\n      // Check if already process another edge between same 2 nodes\n      if (dist[sourceIndex][targetIndex] > weight) {\n        dist[sourceIndex][targetIndex] = weight;\n        next[sourceIndex][targetIndex] = targetIndex;\n        edgeNext[sourceIndex][targetIndex] = edges[i];\n      }\n    }\n\n    // If undirected graph, process 'reversed' edges\n    if (!directed) {\n      for (var i = 0; i < edges.length ; i++) {\n        var sourceIndex = id2position[edges[i].target().id()];\n        var targetIndex = id2position[edges[i].source().id()];\n        var weight = weightFn.apply(edges[i], [edges[i]]);\n\n        // Check if already process another edge between same 2 nodes\n        if (dist[sourceIndex][targetIndex] > weight) {\n          dist[sourceIndex][targetIndex] = weight;\n          next[sourceIndex][targetIndex] = targetIndex;\n          edgeNext[sourceIndex][targetIndex] = edges[i];\n        }\n      }\n    }\n\n    // Main loop\n    for (var k = 0; k < numNodes; k++) {\n      for (var i = 0; i < numNodes; i++) {\n        for (var j = 0; j < numNodes; j++) {\n          if (dist[i][k] + dist[k][j] < dist[i][j]) {\n            dist[i][j] = dist[i][k] + dist[k][j];\n            next[i][j] = next[i][k];\n          }\n        }\n      }\n    }\n\n    // Build result object\n    var position2id = [];\n    for (var i = 0; i < numNodes; i++) {\n      position2id.push(nodes[i].id());\n    }\n\n    var res = {\n      distance: function(from, to) {\n        if (is.string(from)) {\n          // from is a selector string\n          var fromId = (cy.filter(from)[0]).id();\n        } else {\n          // from is a node\n          var fromId = from.id();\n        }\n\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n\n        return dist[id2position[fromId]][id2position[toId]];\n      },\n\n      path: function(from, to) {\n        var reconstructPathAux = function(from, to, next, position2id, edgeNext) {\n          if (from === to) {\n            return cy.getElementById( position2id[from] );\n          }\n          if (next[from][to] === undefined) {\n            return undefined;\n          }\n\n          var path = [ cy.getElementById(position2id[from]) ];\n          var prev = from;\n          while (from !== to) {\n            prev = from;\n            from = next[from][to];\n\n            var edge = edgeNext[prev][from];\n            path.push( edge );\n\n            path.push( cy.getElementById(position2id[from]) );\n          }\n          return path;\n        };\n\n        if (is.string(from)) {\n          // from is a selector string\n          var fromId = (cy.filter(from)[0]).id();\n        } else {\n          // from is a node\n          var fromId = from.id();\n        }\n\n        if (is.string(to)) {\n          // to is a selector string\n          var toId = (cy.filter(to)[0]).id();\n        } else {\n          // to is a node\n          var toId = to.id();\n        }\n\n        var pathArr = reconstructPathAux(id2position[fromId],\n                      id2position[toId],\n                      next,\n                      position2id,\n                      edgeNext);\n\n        return cy.collection( pathArr );\n      }\n    };\n\n    return res;\n\n  } // floydWarshall\n\n}); // elesfn\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../../util');\n\nvar elesfn = {};\n\n[\n  require('./bfs-dfs'),\n  require('./a-star'),\n  require('./floyd-warshall'),\n  require('./bellman-ford'),\n  require('./kerger-stein'),\n  require('./page-rank'),\n  require('./degree-centrality'),\n  require('./closeness-centrality'),\n  require('./betweenness-centrality')\n].forEach(function( props ){\n  util.extend( elesfn, props );\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../../util');\n\nvar elesfn = ({\n\n  // Computes the minimum cut of an undirected graph\n  // Returns the correct answer with high probability\n  kargerStein: function(options) {\n    var eles = this;\n\n    options = options || {};\n\n    // Function which colapses 2 (meta) nodes into one\n    // Updates the remaining edge lists\n    // Receives as a paramater the edge which causes the collapse\n    var colapse = function(edgeIndex, nodeMap, remainingEdges) {\n      var edgeInfo = remainingEdges[edgeIndex];\n      var sourceIn = edgeInfo[1];\n      var targetIn = edgeInfo[2];\n      var partition1 = nodeMap[sourceIn];\n      var partition2 = nodeMap[targetIn];\n\n      // Delete all edges between partition1 and partition2\n      var newEdges = remainingEdges.filter(function(edge) {\n        if (nodeMap[edge[1]] === partition1 && nodeMap[edge[2]] === partition2) {\n          return false;\n        }\n        if (nodeMap[edge[1]] === partition2 && nodeMap[edge[2]] === partition1) {\n          return false;\n        }\n        return true;\n      });\n\n      // All edges pointing to partition2 should now point to partition1\n      for (var i = 0; i < newEdges.length; i++) {\n        var edge = newEdges[i];\n        if (edge[1] === partition2) { // Check source\n          newEdges[i] = edge.slice(0);\n          newEdges[i][1] = partition1;\n        } else if (edge[2] === partition2) { // Check target\n          newEdges[i] = edge.slice(0);\n          newEdges[i][2] = partition1;\n        }\n      }\n\n      // Move all nodes from partition2 to partition1\n      for (var i = 0; i < nodeMap.length; i++) {\n        if (nodeMap[i] === partition2) {\n          nodeMap[i] = partition1;\n        }\n      }\n\n      return newEdges;\n    };\n\n\n    // Contracts a graph until we reach a certain number of meta nodes\n    var contractUntil = function(metaNodeMap,\n                   remainingEdges,\n                   size,\n                   sizeLimit) {\n      // Stop condition\n      if (size <= sizeLimit) {\n        return remainingEdges;\n      }\n\n      // Choose an edge randomly\n      var edgeIndex = Math.floor((Math.random() * remainingEdges.length));\n\n      // Colapse graph based on edge\n      var newEdges = colapse(edgeIndex, metaNodeMap, remainingEdges);\n\n      return contractUntil(metaNodeMap,\n                 newEdges,\n                 size - 1,\n                 sizeLimit);\n    };\n\n    var cy = this._private.cy;\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n    var numEdges = edges.length;\n    var numIter = Math.ceil(Math.pow(Math.log(numNodes) / Math.LN2, 2));\n    var stopSize = Math.floor(numNodes / Math.sqrt(2));\n\n    if (numNodes < 2) {\n      util.error(\"At least 2 nodes are required for Karger-Stein algorithm\");\n      return undefined;\n    }\n\n    // Create numerical identifiers for each node\n    // mapping: node id -> position in nodes array\n    // for reverse mapping, simply use nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Now store edge destination as indexes\n    // Format for each edge (edge index, source node index, target node index)\n    var edgeIndexes = [];\n    for (var i = 0; i < numEdges; i++) {\n      var e = edges[i];\n      edgeIndexes.push([i, id2position[e.source().id()], id2position[e.target().id()]]);\n    }\n\n    // We will store the best cut found here\n    var minCutSize = Infinity;\n    var minCut;\n\n    // Initial meta node partition\n    var originalMetaNode = [];\n    for (var i = 0; i < numNodes; i++) {\n      originalMetaNode.push(i);\n    }\n\n    // Main loop\n    for (var iter = 0; iter <= numIter; iter++) {\n      // Create new meta node partition\n      var metaNodeMap = originalMetaNode.slice(0);\n\n      // Contract until stop point (stopSize nodes)\n      var edgesState = contractUntil(metaNodeMap, edgeIndexes, numNodes, stopSize);\n\n      // Create a copy of the colapsed nodes state\n      var metaNodeMap2 = metaNodeMap.slice(0);\n\n      // Run 2 iterations starting in the stop state\n      var res1 = contractUntil(metaNodeMap, edgesState, stopSize, 2);\n      var res2 = contractUntil(metaNodeMap2, edgesState, stopSize, 2);\n\n      // Is any of the 2 results the best cut so far?\n      if (res1.length <= res2.length && res1.length < minCutSize) {\n        minCutSize = res1.length;\n        minCut = [res1, metaNodeMap];\n      } else if (res2.length <= res1.length && res2.length < minCutSize) {\n        minCutSize = res2.length;\n        minCut = [res2, metaNodeMap2];\n      }\n    } // end of main loop\n\n\n    // Construct result\n    var resEdges = (minCut[0]).map(function(e){ return edges[e[0]]; });\n    var partition1 = [];\n    var partition2 = [];\n\n    // traverse metaNodeMap for best cut\n    var witnessNodePartition = minCut[1][0];\n    for (var i = 0; i < minCut[1].length; i++) {\n      var partitionId = minCut[1][i];\n      if (partitionId === witnessNodePartition) {\n        partition1.push(nodes[i]);\n      } else {\n        partition2.push(nodes[i]);\n      }\n    }\n\n    var ret = {\n      cut: eles.spawn(cy, resEdges),\n      partition1: eles.spawn(partition1),\n      partition2: eles.spawn(partition2)\n    };\n\n    return ret;\n  }\n}); // elesfn\n\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n  pageRank: function(options) {\n    options = options || {};\n\n    var normalizeVector = function(vector) {\n      var length = vector.length;\n\n      // First, get sum of all elements\n      var total = 0;\n      for (var i = 0; i < length; i++) {\n        total += vector[i];\n      }\n\n      // Now, divide each by the sum of all elements\n      for (var i = 0; i < length; i++) {\n        vector[i] = vector[i] / total;\n      }\n    };\n\n    // dampingFactor - optional\n    if (options != null &&\n      options.dampingFactor != null) {\n      var dampingFactor = options.dampingFactor;\n    } else {\n      var dampingFactor = 0.8; // Default damping factor\n    }\n\n    // desired precision - optional\n    if (options != null &&\n      options.precision != null) {\n      var epsilon = options.precision;\n    } else {\n      var epsilon = 0.000001; // Default precision\n    }\n\n    // Max number of iterations - optional\n    if (options != null &&\n      options.iterations != null) {\n      var numIter = options.iterations;\n    } else {\n      var numIter = 200; // Default number of iterations\n    }\n\n    // Weight function - optional\n    if (options != null &&\n      options.weight != null &&\n      is.fn(options.weight)) {\n      var weightFn = options.weight;\n    } else {\n      // If not specified, assume each edge has equal weight (1)\n      var weightFn = function(e) {return 1;};\n    }\n\n    var cy = this._private.cy;\n    var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n    var nodes = this.nodes();\n    var numNodes = nodes.length;\n    var numEdges = edges.length;\n\n    // Create numerical identifiers for each node\n    // mapping: node id -> position in nodes array\n    // for reverse mapping, simply use nodes array\n    var id2position = {};\n    for (var i = 0; i < numNodes; i++) {\n      id2position[nodes[i].id()] = i;\n    }\n\n    // Construct transposed adjacency matrix\n    // First lets have a zeroed matrix of the right size\n    // We'll also keep track of the sum of each column\n    var matrix = [];\n    var columnSum = [];\n    var additionalProb = (1 - dampingFactor) / numNodes;\n\n    // Create null matric\n    for (var i = 0; i < numNodes; i++) {\n      var newRow = [];\n      for (var j = 0; j < numNodes; j++) {\n        newRow.push(0.0);\n      }\n      matrix.push(newRow);\n      columnSum.push(0.0);\n    }\n\n    // Now, process edges\n    for (var i = 0; i < numEdges; i++) {\n      var edge = edges[i];\n      var s = id2position[edge.source().id()];\n      var t = id2position[edge.target().id()];\n      var w = weightFn.apply(edge, [edge]);\n\n      // Update matrix\n      matrix[t][s] += w;\n\n      // Update column sum\n      columnSum[s] += w;\n    }\n\n    // Add additional probability based on damping factor\n    // Also, take into account columns that have sum = 0\n    var p = 1.0 / numNodes + additionalProb; // Shorthand\n    // Traverse matrix, column by column\n    for (var j = 0; j < numNodes; j++) {\n      if (columnSum[j] === 0) {\n        // No 'links' out from node jth, assume equal probability for each possible node\n        for (var i = 0; i < numNodes; i++) {\n          matrix[i][j] = p;\n        }\n      } else {\n        // Node jth has outgoing link, compute normalized probabilities\n        for (var i = 0; i < numNodes; i++) {\n          matrix[i][j] = matrix[i][j] / columnSum[j] + additionalProb;\n        }\n      }\n    }\n\n    // Compute dominant eigenvector using power method\n    var eigenvector = [];\n    var nullVector = [];\n    var previous;\n\n    // Start with a vector of all 1's\n    // Also, initialize a null vector which will be used as shorthand\n    for (var i = 0; i < numNodes; i++) {\n      eigenvector.push(1.0);\n      nullVector.push(0.0);\n    }\n\n    for (var iter = 0; iter < numIter; iter++) {\n      // New array with all 0's\n      var temp = nullVector.slice(0);\n\n      // Multiply matrix with previous result\n      for (var i = 0; i < numNodes; i++) {\n        for (var j = 0; j < numNodes; j++) {\n          temp[i] += matrix[i][j] * eigenvector[j];\n        }\n      }\n\n      normalizeVector(temp);\n      previous = eigenvector;\n      eigenvector = temp;\n\n      var diff = 0;\n      // Compute difference (squared module) of both vectors\n      for (var i = 0; i < numNodes; i++) {\n        diff += Math.pow(previous[i] - eigenvector[i], 2);\n      }\n\n      // If difference is less than the desired threshold, stop iterating\n      if (diff < epsilon) {\n        break;\n      }\n    }\n\n    // Construct result\n    var res = {\n      rank : function(node) {\n        if (is.string(node)) {\n          // is a selector string\n          var nodeId = (cy.filter(node)[0]).id();\n        } else {\n          // is a node object\n          var nodeId = node.id();\n        }\n        return eigenvector[id2position[nodeId]];\n      }\n    };\n\n\n    return res;\n  } // pageRank\n\n}); // elesfn\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar define = require('../define');\n\nvar elesfn = ({\n  animate: define.animate(),\n  animation: define.animation(),\n  animated: define.animated(),\n  clearQueue: define.clearQueue(),\n  delay: define.delay(),\n  delayAnimation: define.delayAnimation(),\n  stop: define.stop()\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\n\nvar elesfn = ({\n  classes: function( classes ){\n    classes = classes.match(/\\S+/g) || [];\n    var self = this;\n    var changed = [];\n    var classesMap = {};\n\n    // fill in classes map\n    for( var i = 0; i < classes.length; i++ ){\n      var cls = classes[i];\n\n      classesMap[ cls ] = true;\n    }\n\n    // check and update each ele\n    for( var j = 0; j < self.length; j++ ){\n      var ele = self[j];\n      var _p = ele._private;\n      var eleClasses = _p.classes;\n      var changedEle = false;\n\n      // check if ele has all of the passed classes\n      for( var i = 0; i < classes.length; i++ ){\n        var cls = classes[i];\n        var eleHasClass = eleClasses[ cls ];\n\n        if( !eleHasClass ){\n          changedEle = true;\n          break;\n        }\n      }\n\n      // check if ele has classes outside of those passed\n      if( !changedEle ){ for( var eleCls in eleClasses ){\n        var eleHasClass = eleClasses[ eleCls ];\n        var specdClass = classesMap[ eleCls ]; // i.e. this class is passed to the function\n\n        if( eleHasClass && !specdClass ){\n          changedEle = true;\n          break;\n        }\n      } }\n\n      if( changedEle ){\n        _p.classes = util.copy( classesMap );\n\n        changed.push( ele );\n      }\n    }\n\n    // trigger update style on those eles that had class changes\n    if( changed.length > 0 ){\n      this.spawn(changed)\n        .updateStyle()\n        .trigger('class')\n      ;\n    }\n\n    return self;\n  },\n\n  addClass: function( classes ){\n    return this.toggleClass( classes, true );\n  },\n\n  hasClass: function( className ){\n    var ele = this[0];\n    return ( ele != null && ele._private.classes[className] ) ? true : false;\n  },\n\n  toggleClass: function( classesStr, toggle ){\n    var classes = classesStr.match(/\\S+/g) || [];\n    var self = this;\n    var changed = []; // eles who had classes changed\n\n    for( var i = 0, il = self.length; i < il; i++ ){\n      var ele = self[i];\n      var changedEle = false;\n\n      for( var j = 0; j < classes.length; j++ ){\n        var cls = classes[j];\n        var eleClasses = ele._private.classes;\n        var hasClass = eleClasses[cls];\n        var shouldAdd = toggle || (toggle === undefined && !hasClass);\n\n        if( shouldAdd ){\n          eleClasses[cls] = true;\n\n          if( !hasClass && !changedEle ){\n            changed.push(ele);\n            changedEle = true;\n          }\n        } else { // then remove\n          eleClasses[cls] = false;\n\n          if( hasClass && !changedEle ){\n            changed.push(ele);\n            changedEle = true;\n          }\n        }\n\n      } // for j classes\n    } // for i eles\n\n    // trigger update style on those eles that had class changes\n    if( changed.length > 0 ){\n      this.spawn(changed)\n        .updateStyle()\n        .trigger('class')\n      ;\n    }\n\n    return self;\n  },\n\n  removeClass: function( classes ){\n    return this.toggleClass( classes, false );\n  },\n\n  flashClass: function( classes, duration ){\n    var self = this;\n\n    if( duration == null ){\n      duration = 250;\n    } else if( duration === 0 ){\n      return self; // nothing to do really\n    }\n\n    self.addClass( classes );\n    setTimeout(function(){\n      self.removeClass( classes );\n    }, duration);\n\n    return self;\n  }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = ({\n  allAre: function( selector ){\n    return this.filter(selector).length === this.length;\n  },\n\n  is: function( selector ){\n    return this.filter(selector).length > 0;\n  },\n\n  some: function( fn, thisArg ){\n    for( var i = 0; i < this.length; i++ ){\n      var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );\n\n      if( ret ){\n        return true;\n      }\n    }\n\n    return false;\n  },\n\n  every: function( fn, thisArg ){\n    for( var i = 0; i < this.length; i++ ){\n      var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );\n\n      if( !ret ){\n        return false;\n      }\n    }\n\n    return true;\n  },\n\n  same: function( collection ){\n    collection = this.cy().collection( collection );\n\n    // cheap extra check\n    if( this.length !== collection.length ){\n      return false;\n    }\n\n    return this.intersect( collection ).length === this.length;\n  },\n\n  anySame: function( collection ){\n    collection = this.cy().collection( collection );\n\n    return this.intersect( collection ).length > 0;\n  },\n\n  allAreNeighbors: function( collection ){\n    collection = this.cy().collection( collection );\n\n    return this.neighborhood().intersect( collection ).length === collection.length;\n  }\n});\n\nelesfn.allAreNeighbours = elesfn.allAreNeighbors;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = ({\n  parent: function( selector ){\n    var parents = [];\n    var cy = this._private.cy;\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      var parent = cy.getElementById( ele._private.data.parent );\n\n      if( parent.size() > 0 ){\n        parents.push( parent );\n      }\n    }\n\n    return this.spawn( parents, { unique: true } ).filter( selector );\n  },\n\n  parents: function( selector ){\n    var parents = [];\n\n    var eles = this.parent();\n    while( eles.nonempty() ){\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n        parents.push( ele );\n      }\n\n      eles = eles.parent();\n    }\n\n    return this.spawn( parents, { unique: true } ).filter( selector );\n  },\n\n  commonAncestors: function( selector ){\n    var ancestors;\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      var parents = ele.parents();\n\n      ancestors = ancestors || parents;\n\n      ancestors = ancestors.intersect( parents ); // current list must be common with current ele parents set\n    }\n\n    return ancestors.filter( selector );\n  },\n\n  orphans: function( selector ){\n    return this.stdFilter(function( ele ){\n      return ele.isNode() && ele.parent().empty();\n    }).filter( selector );\n  },\n\n  nonorphans: function( selector ){\n    return this.stdFilter(function( ele ){\n      return ele.isNode() && ele.parent().nonempty();\n    }).filter( selector );\n  },\n\n  children: function( selector ){\n    var children = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      children = children.concat( ele._private.children );\n    }\n\n    return this.spawn( children, { unique: true } ).filter( selector );\n  },\n\n  siblings: function( selector ){\n    return this.parent().children().not( this ).filter( selector );\n  },\n\n  isParent: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.children.length !== 0;\n    }\n  },\n\n  isChild: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.data.parent !== undefined && ele.parent().length !== 0;\n    }\n  },\n\n  descendants: function( selector ){\n    var elements = [];\n\n    function add( eles ){\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        elements.push( ele );\n\n        if( ele.children().nonempty() ){\n          add( ele.children() );\n        }\n      }\n    }\n\n    add( this.children() );\n\n    return this.spawn( elements, { unique: true } ).filter( selector );\n  }\n});\n\n// aliases\nelesfn.ancestors = elesfn.parents;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar define = require('../define');\nvar fn, elesfn;\n\nfn = elesfn = ({\n\n  data: define.data({\n    field: 'data',\n    bindingEvent: 'data',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'data',\n    settingTriggersEvent: true,\n    triggerFnName: 'trigger',\n    allowGetting: true,\n    immutableKeys: {\n      'id': true,\n      'source': true,\n      'target': true,\n      'parent': true\n    },\n    updateStyle: true\n  }),\n\n  removeData: define.removeData({\n    field: 'data',\n    event: 'data',\n    triggerFnName: 'trigger',\n    triggerEvent: true,\n    immutableKeys: {\n      'id': true,\n      'source': true,\n      'target': true,\n      'parent': true\n    },\n    updateStyle: true\n  }),\n\n  scratch: define.data({\n    field: 'scratch',\n    bindingEvent: 'scratch',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'scratch',\n    settingTriggersEvent: true,\n    triggerFnName: 'trigger',\n    allowGetting: true,\n    updateStyle: true\n  }),\n\n  removeScratch: define.removeData({\n    field: 'scratch',\n    event: 'scratch',\n    triggerFnName: 'trigger',\n    triggerEvent: true,\n    updateStyle: true\n  }),\n\n  rscratch: define.data({\n    field: 'rscratch',\n    allowBinding: false,\n    allowSetting: true,\n    settingTriggersEvent: false,\n    allowGetting: true\n  }),\n\n  removeRscratch: define.removeData({\n    field: 'rscratch',\n    triggerEvent: false\n  }),\n\n  id: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.data.id;\n    }\n  }\n\n});\n\n// aliases\nfn.attr = fn.data;\nfn.removeAttr = fn.removeData;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\n\nvar elesfn = {};\n\nfunction defineDegreeFunction(callback){\n  return function( includeLoops ){\n    var self = this;\n\n    if( includeLoops === undefined ){\n      includeLoops = true;\n    }\n\n    if( self.length === 0 ){ return; }\n\n    if( self.isNode() && !self.removed() ){\n      var degree = 0;\n      var node = self[0];\n      var connectedEdges = node._private.edges;\n\n      for( var i = 0; i < connectedEdges.length; i++ ){\n        var edge = connectedEdges[i];\n\n        if( !includeLoops && edge.isLoop() ){\n          continue;\n        }\n\n        degree += callback( node, edge );\n      }\n\n      return degree;\n    } else {\n      return;\n    }\n  };\n}\n\nutil.extend(elesfn, {\n  degree: defineDegreeFunction(function(node, edge){\n    if( edge.source().same( edge.target() ) ){\n      return 2;\n    } else {\n      return 1;\n    }\n  }),\n\n  indegree: defineDegreeFunction(function(node, edge){\n    if( edge.target().same(node) ){\n      return 1;\n    } else {\n      return 0;\n    }\n  }),\n\n  outdegree: defineDegreeFunction(function(node, edge){\n    if( edge.source().same(node) ){\n      return 1;\n    } else {\n      return 0;\n    }\n  })\n});\n\nfunction defineDegreeBoundsFunction(degreeFn, callback){\n  return function( includeLoops ){\n    var ret;\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){\n      var ele = nodes[i];\n      var degree = ele[degreeFn]( includeLoops );\n      if( degree !== undefined && (ret === undefined || callback(degree, ret)) ){\n        ret = degree;\n      }\n    }\n\n    return ret;\n  };\n}\n\nutil.extend(elesfn, {\n  minDegree: defineDegreeBoundsFunction('degree', function(degree, min){\n    return degree < min;\n  }),\n\n  maxDegree: defineDegreeBoundsFunction('degree', function(degree, max){\n    return degree > max;\n  }),\n\n  minIndegree: defineDegreeBoundsFunction('indegree', function(degree, min){\n    return degree < min;\n  }),\n\n  maxIndegree: defineDegreeBoundsFunction('indegree', function(degree, max){\n    return degree > max;\n  }),\n\n  minOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, min){\n    return degree < min;\n  }),\n\n  maxOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, max){\n    return degree > max;\n  })\n});\n\nutil.extend(elesfn, {\n  totalDegree: function( includeLoops ){\n    var total = 0;\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){\n      total += nodes[i].degree( includeLoops );\n    }\n\n    return total;\n  }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar define = require('../define');\nvar is = require('../is');\nvar util = require('../util');\nvar fn, elesfn;\n\nfn = elesfn = ({\n\n  position: define.data({\n    field: 'position',\n    bindingEvent: 'position',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'position',\n    settingTriggersEvent: true,\n    triggerFnName: 'rtrigger',\n    allowGetting: true,\n    validKeys: ['x', 'y'],\n    onSet: function( eles ){\n      var updatedEles = eles.updateCompoundBounds();\n      updatedEles.rtrigger('position');\n    },\n    canSet: function( ele ){\n      return !ele.locked() && !ele.isParent();\n    }\n  }),\n\n  // position but no notification to renderer\n  silentPosition: define.data({\n    field: 'position',\n    bindingEvent: 'position',\n    allowBinding: false,\n    allowSetting: true,\n    settingEvent: 'position',\n    settingTriggersEvent: false,\n    triggerFnName: 'trigger',\n    allowGetting: true,\n    validKeys: ['x', 'y'],\n    onSet: function( eles ){\n      eles.updateCompoundBounds();\n    },\n    canSet: function( ele ){\n      return !ele.locked() && !ele.isParent();\n    }\n  }),\n\n  positions: function( pos, silent ){\n    if( is.plainObject(pos) ){\n      this.position(pos);\n\n    } else if( is.fn(pos) ){\n      var fn = pos;\n\n      for( var i = 0; i < this.length; i++ ){\n        var ele = this[i];\n\n        var pos = fn.apply(ele, [i, ele]);\n\n        if( pos && !ele.locked() && !ele.isParent() ){\n          var elePos = ele._private.position;\n          elePos.x = pos.x;\n          elePos.y = pos.y;\n        }\n      }\n\n      var updatedEles = this.updateCompoundBounds();\n      var toTrigger = updatedEles.length > 0 ? this.add( updatedEles ) : this;\n\n      if( silent ){\n        toTrigger.trigger('position');\n      } else {\n        toTrigger.rtrigger('position');\n      }\n    }\n\n    return this; // chaining\n  },\n\n  silentPositions: function( pos ){\n    return this.positions( pos, true );\n  },\n\n  // get/set the rendered (i.e. on screen) positon of the element\n  renderedPosition: function( dim, val ){\n    var ele = this[0];\n    var cy = this.cy();\n    var zoom = cy.zoom();\n    var pan = cy.pan();\n    var rpos = is.plainObject( dim ) ? dim : undefined;\n    var setting = rpos !== undefined || ( val !== undefined && is.string(dim) );\n\n    if( ele && ele.isNode() ){ // must have an element and must be a node to return position\n      if( setting ){\n        for( var i = 0; i < this.length; i++ ){\n          var ele = this[i];\n\n          if( val !== undefined ){ // set one dimension\n            ele._private.position[dim] = ( val - pan[dim] )/zoom;\n          } else if( rpos !== undefined ){ // set whole position\n            ele._private.position = {\n              x: ( rpos.x - pan.x ) /zoom,\n              y: ( rpos.y - pan.y ) /zoom\n            };\n          }\n        }\n\n        this.rtrigger('position');\n      } else { // getting\n        var pos = ele._private.position;\n        rpos = {\n          x: pos.x * zoom + pan.x,\n          y: pos.y * zoom + pan.y\n        };\n\n        if( dim === undefined ){ // then return the whole rendered position\n          return rpos;\n        } else { // then return the specified dimension\n          return rpos[ dim ];\n        }\n      }\n    } else if( !setting ){\n      return undefined; // for empty collection case\n    }\n\n    return this; // chaining\n  },\n\n  // get/set the position relative to the parent\n  relativePosition: function( dim, val ){\n    var ele = this[0];\n    var cy = this.cy();\n    var ppos = is.plainObject( dim ) ? dim : undefined;\n    var setting = ppos !== undefined || ( val !== undefined && is.string(dim) );\n    var hasCompoundNodes = cy.hasCompoundNodes();\n\n    if( ele && ele.isNode() ){ // must have an element and must be a node to return position\n      if( setting ){\n        for( var i = 0; i < this.length; i++ ){\n          var ele = this[i];\n          var parent = hasCompoundNodes ? ele.parent() : null;\n          var hasParent = parent && parent.length > 0;\n          var relativeToParent = hasParent;\n\n          if( hasParent ){\n            parent = parent[0];\n          }\n\n          var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };\n\n          if( val !== undefined ){ // set one dimension\n            ele._private.position[dim] = val + origin[dim];\n          } else if( ppos !== undefined ){ // set whole position\n            ele._private.position = {\n              x: ppos.x + origin.x,\n              y: ppos.y + origin.y\n            };\n          }\n        }\n\n        this.rtrigger('position');\n\n      } else { // getting\n        var pos = ele._private.position;\n        var parent = hasCompoundNodes ? ele.parent() : null;\n        var hasParent = parent && parent.length > 0;\n        var relativeToParent = hasParent;\n\n        if( hasParent ){\n          parent = parent[0];\n        }\n\n        var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };\n\n        ppos = {\n          x: pos.x - origin.x,\n          y: pos.y - origin.y\n        };\n\n        if( dim === undefined ){ // then return the whole rendered position\n          return ppos;\n        } else { // then return the specified dimension\n          return ppos[ dim ];\n        }\n      }\n    } else if( !setting ){\n      return undefined; // for empty collection case\n    }\n\n    return this; // chaining\n  },\n\n  renderedBoundingBox: function( options ){\n    var bb = this.boundingBox( options );\n    var cy = this.cy();\n    var zoom = cy.zoom();\n    var pan = cy.pan();\n\n    var x1 = bb.x1 * zoom + pan.x;\n    var x2 = bb.x2 * zoom + pan.x;\n    var y1 = bb.y1 * zoom + pan.y;\n    var y2 = bb.y2 * zoom + pan.y;\n\n    return {\n      x1: x1,\n      x2: x2,\n      y1: y1,\n      y2: y2,\n      w: x2 - x1,\n      h: y2 - y1\n    };\n  },\n\n  updateCompoundBounds: function(){\n    var cy = this.cy();\n\n    if( !cy.styleEnabled() || !cy.hasCompoundNodes() ){ return cy.collection(); } // save cycles for non compound graphs or when style disabled\n\n    var updated = [];\n\n    function update( parent ){\n      var children = parent.children();\n      var style = parent._private.style;\n      var includeLabels = style['compound-sizing-wrt-labels'].value === 'include';\n      var bb = children.boundingBox({ includeLabels: includeLabels, includeEdges: true });\n      var padding = {\n        top: style['padding-top'].pfValue,\n        bottom: style['padding-bottom'].pfValue,\n        left: style['padding-left'].pfValue,\n        right: style['padding-right'].pfValue\n      };\n      var pos = parent._private.position;\n      var didUpdate = false;\n\n      if( style['width'].value === 'auto' ){\n        parent._private.autoWidth = bb.w;\n        pos.x = (bb.x1 + bb.x2 - padding.left + padding.right)/2;\n        didUpdate = true;\n      }\n\n      if( style['height'].value === 'auto' ){\n        parent._private.autoHeight = bb.h;\n        pos.y = (bb.y1 + bb.y2 - padding.top + padding.bottom)/2;\n        didUpdate = true;\n      }\n\n      if( didUpdate ){\n        updated.push( parent );\n      }\n    }\n\n    // go up, level by level\n    var eles = this.parent();\n    while( eles.nonempty() ){\n\n      // update each parent node in this level\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        update( ele );\n      }\n\n      // next level\n      eles = eles.parent();\n    }\n\n    // return changed\n    return this.spawn( updated );\n  },\n\n  // get the bounding box of the elements (in raw model position)\n  boundingBox: function( options ){\n    var eles = this;\n    var cy = eles._private.cy;\n    var cy_p = cy._private;\n    var styleEnabled = cy_p.styleEnabled;\n\n    options = options || util.staticEmptyObject();\n\n    var includeNodes = options.includeNodes === undefined ? true : options.includeNodes;\n    var includeEdges = options.includeEdges === undefined ? true : options.includeEdges;\n    var includeLabels = options.includeLabels === undefined ? true : options.includeLabels;\n\n    // recalculate projections etc\n    if( styleEnabled ){\n      cy_p.renderer.recalculateRenderedStyle( this );\n    }\n\n    var x1 = Infinity;\n    var x2 = -Infinity;\n    var y1 = Infinity;\n    var y2 = -Infinity;\n\n    // find bounds of elements\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var _p = ele._private;\n      var style = _p.style;\n      var display = styleEnabled ? _p.style['display'].value : 'element';\n      var isNode = _p.group === 'nodes';\n      var ex1, ex2, ey1, ey2, x, y;\n      var includedEle = false;\n\n      if( display === 'none' ){ continue; } // then ele doesn't take up space\n\n      if( isNode && includeNodes ){\n        includedEle = true;\n\n        var pos = _p.position;\n        x = pos.x;\n        y = pos.y;\n        var w = ele.outerWidth();\n        var halfW = w/2;\n        var h = ele.outerHeight();\n        var halfH = h/2;\n\n        // handle node dimensions\n        /////////////////////////\n\n        ex1 = x - halfW;\n        ex2 = x + halfW;\n        ey1 = y - halfH;\n        ey2 = y + halfH;\n\n        x1 = ex1 < x1 ? ex1 : x1;\n        x2 = ex2 > x2 ? ex2 : x2;\n        y1 = ey1 < y1 ? ey1 : y1;\n        y2 = ey2 > y2 ? ey2 : y2;\n\n      } else if( ele.isEdge() && includeEdges ){\n        includedEle = true;\n\n        var n1 = _p.source;\n        var n1_p = n1._private;\n        var n1pos = n1_p.position;\n\n        var n2 = _p.target;\n        var n2_p = n2._private;\n        var n2pos = n2_p.position;\n\n\n        // handle edge dimensions (rough box estimate)\n        //////////////////////////////////////////////\n\n        var rstyle = _p.rstyle || {};\n        var w = 0;\n        var wHalf = 0;\n\n        if( styleEnabled ){\n          w = style['width'].pfValue;\n          wHalf = w/2;\n        }\n\n        ex1 = n1pos.x;\n        ex2 = n2pos.x;\n        ey1 = n1pos.y;\n        ey2 = n2pos.y;\n\n        if( ex1 > ex2 ){\n          var temp = ex1;\n          ex1 = ex2;\n          ex2 = temp;\n        }\n\n        if( ey1 > ey2 ){\n          var temp = ey1;\n          ey1 = ey2;\n          ey2 = temp;\n        }\n\n        // take into account edge width\n        ex1 -= wHalf;\n        ex2 += wHalf;\n        ey1 -= wHalf;\n        ey2 += wHalf;\n\n        x1 = ex1 < x1 ? ex1 : x1;\n        x2 = ex2 > x2 ? ex2 : x2;\n        y1 = ey1 < y1 ? ey1 : y1;\n        y2 = ey2 > y2 ? ey2 : y2;\n\n        // handle points along edge (sanity check)\n        //////////////////////////////////////////\n\n        if( styleEnabled ){\n          var pts = rstyle.bezierPts || rstyle.linePts || [];\n\n          for( var j = 0; j < pts.length; j++ ){\n            var pt = pts[j];\n\n            ex1 = pt.x - wHalf;\n            ex2 = pt.x + wHalf;\n            ey1 = pt.y - wHalf;\n            ey2 = pt.y + wHalf;\n\n            x1 = ex1 < x1 ? ex1 : x1;\n            x2 = ex2 > x2 ? ex2 : x2;\n            y1 = ey1 < y1 ? ey1 : y1;\n            y2 = ey2 > y2 ? ey2 : y2;\n          }\n        }\n\n        // precise haystacks (sanity check)\n        ///////////////////////////////////\n\n        if( styleEnabled && style['curve-style'].strValue === 'haystack' ){\n          var hpts = rstyle.haystackPts;\n\n          ex1 = hpts[0].x;\n          ey1 = hpts[0].y;\n          ex2 = hpts[1].x;\n          ey2 = hpts[1].y;\n\n          if( ex1 > ex2 ){\n            var temp = ex1;\n            ex1 = ex2;\n            ex2 = temp;\n          }\n\n          if( ey1 > ey2 ){\n            var temp = ey1;\n            ey1 = ey2;\n            ey2 = temp;\n          }\n\n          x1 = ex1 < x1 ? ex1 : x1;\n          x2 = ex2 > x2 ? ex2 : x2;\n          y1 = ey1 < y1 ? ey1 : y1;\n          y2 = ey2 > y2 ? ey2 : y2;\n        }\n\n      } // edges\n\n\n      // handle label dimensions\n      //////////////////////////\n\n      if( styleEnabled ){\n\n        var _p = ele._private;\n        var style = _p.style;\n        var rstyle = _p.rstyle;\n        var label = style['label'].strValue;\n        var fontSize = style['font-size'];\n        var halign = style['text-halign'];\n        var valign = style['text-valign'];\n        var labelWidth = rstyle.labelWidth;\n        var labelHeight = rstyle.labelHeight;\n        var labelX = rstyle.labelX;\n        var labelY = rstyle.labelY;\n        var isEdge = ele.isEdge();\n        var autorotate = style['edge-text-rotation'].strValue === 'autorotate';\n\n        if( includeLabels && label && fontSize && labelHeight != null && labelWidth != null && labelX != null && labelY != null && halign && valign ){\n          var lh = labelHeight;\n          var lw = labelWidth;\n          var lx1, lx2, ly1, ly2;\n\n          if( isEdge ){\n            lx1 = labelX - lw/2;\n            lx2 = labelX + lw/2;\n            ly1 = labelY - lh/2;\n            ly2 = labelY + lh/2;\n\n            if( autorotate ){\n              var theta = _p.rscratch.labelAngle;\n              var cos = Math.cos( theta );\n              var sin = Math.sin( theta );\n\n              var rotate = function( x, y ){\n                x = x - labelX;\n                y = y - labelY;\n\n                return {\n                  x: x*cos - y*sin + labelX,\n                  y: x*sin + y*cos + labelY\n                };\n              };\n\n              var px1y1 = rotate( lx1, ly1 );\n              var px1y2 = rotate( lx1, ly2 );\n              var px2y1 = rotate( lx2, ly1 );\n              var px2y2 = rotate( lx2, ly2 );\n\n              lx1 = Math.min( px1y1.x, px1y2.x, px2y1.x, px2y2.x );\n              lx2 = Math.max( px1y1.x, px1y2.x, px2y1.x, px2y2.x );\n              ly1 = Math.min( px1y1.y, px1y2.y, px2y1.y, px2y2.y );\n              ly2 = Math.max( px1y1.y, px1y2.y, px2y1.y, px2y2.y );\n            }\n          } else {\n            switch( halign.value ){\n              case 'left':\n                lx1 = labelX - lw;\n                lx2 = labelX;\n                break;\n\n              case 'center':\n                lx1 = labelX - lw/2;\n                lx2 = labelX + lw/2;\n                break;\n\n              case 'right':\n                lx1 = labelX;\n                lx2 = labelX + lw;\n                break;\n            }\n\n            switch( valign.value ){\n              case 'top':\n                ly1 = labelY - lh;\n                ly2 = labelY;\n                break;\n\n              case 'center':\n                ly1 = labelY - lh/2;\n                ly2 = labelY + lh/2;\n                break;\n\n              case 'bottom':\n                ly1 = labelY;\n                ly2 = labelY + lh;\n                break;\n            }\n          }\n\n          x1 = lx1 < x1 ? lx1 : x1;\n          x2 = lx2 > x2 ? lx2 : x2;\n          y1 = ly1 < y1 ? ly1 : y1;\n          y2 = ly2 > y2 ? ly2 : y2;\n        }\n      } // style enabled for labels\n    } // for\n\n    var noninf = function(x){\n      if( x === Infinity || x === -Infinity ){\n        return 0;\n      }\n\n      return x;\n    };\n\n    x1 = noninf(x1);\n    x2 = noninf(x2);\n    y1 = noninf(y1);\n    y2 = noninf(y2);\n\n    return {\n      x1: x1,\n      x2: x2,\n      y1: y1,\n      y2: y2,\n      w: x2 - x1,\n      h: y2 - y1\n    };\n  }\n});\n\nvar defineDimFns = function( opts ){\n  opts.uppercaseName = util.capitalize( opts.name );\n  opts.autoName = 'auto' + opts.uppercaseName;\n  opts.labelName = 'label' + opts.uppercaseName;\n  opts.outerName = 'outer' + opts.uppercaseName;\n  opts.uppercaseOuterName = util.capitalize( opts.outerName );\n\n  fn[ opts.name ] = function dimImpl(){\n    var ele = this[0];\n    var _p = ele._private;\n    var cy = _p.cy;\n    var styleEnabled = cy._private.styleEnabled;\n\n    if( ele ){\n      if( styleEnabled ){\n        var d = _p.style[ opts.name ];\n\n        switch( d.strValue ){\n          case 'auto':\n            return _p[ opts.autoName ] || 0;\n          case 'label':\n            return _p.rstyle[ opts.labelName ] || 0;\n          default:\n            return d.pfValue;\n        }\n      } else {\n        return 1;\n      }\n    }\n  };\n\n  fn[ 'outer' + opts.uppercaseName ] = function outerDimImpl(){\n    var ele = this[0];\n    var _p = ele._private;\n    var cy = _p.cy;\n    var styleEnabled = cy._private.styleEnabled;\n\n    if( ele ){\n      if( styleEnabled ){\n        var style = _p.style;\n        var dim = ele[ opts.name ]();\n        var border = style['border-width'].pfValue;\n        var padding = style[ opts.paddings[0] ].pfValue + style[ opts.paddings[1] ].pfValue;\n\n        return dim + border + padding;\n      } else {\n        return 1;\n      }\n    }\n  };\n\n  fn[ 'rendered' + opts.uppercaseName ] = function renderedDimImpl(){\n    var ele = this[0];\n\n    if( ele ){\n      var d = ele[ opts.name ]();\n      return d * this.cy().zoom();\n    }\n  };\n\n  fn[ 'rendered' + opts.uppercaseOuterName ] = function renderedOuterDimImpl(){\n    var ele = this[0];\n\n    if( ele ){\n      var od = ele[ opts.outerName ]();\n      return od * this.cy().zoom();\n    }\n  };\n};\n\ndefineDimFns({\n  name: 'width',\n  paddings: ['padding-left', 'padding-right']\n});\n\ndefineDimFns({\n  name: 'height',\n  paddings: ['padding-top', 'padding-bottom']\n});\n\n// aliases\nfn.modelPosition = fn.point = fn.position;\nfn.modelPositions = fn.points = fn.positions;\nfn.renderedPoint = fn.renderedPosition;\nfn.relativePoint = fn.relativePosition;\nfn.boundingbox = fn.boundingBox;\nfn.renderedBoundingbox = fn.renderedBoundingBox;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\n// represents a node or an edge\nvar Element = function(cy, params, restore){\n  if( !(this instanceof Element) ){\n    return new Element(cy, params, restore);\n  }\n\n  var self = this;\n  restore = (restore === undefined || restore ? true : false);\n\n  if( cy === undefined || params === undefined || !is.core(cy) ){\n    util.error('An element must have a core reference and parameters set');\n    return;\n  }\n\n  var group = params.group;\n\n  // try to automatically infer the group if unspecified\n  if( group == null ){\n    if( params.data.source != null && params.data.target != null ){\n      group = 'edges';\n    } else {\n      group = 'nodes';\n    }\n  }\n\n  // validate group\n  if( group !== 'nodes' && group !== 'edges' ){\n    util.error('An element must be of type `nodes` or `edges`; you specified `' + group + '`');\n    return;\n  }\n\n  // make the element array-like, just like a collection\n  this.length = 1;\n  this[0] = this;\n\n  // NOTE: when something is added here, add also to ele.json()\n  this._private = {\n    cy: cy,\n    single: true, // indicates this is an element\n    data: params.data || {}, // data object\n    position: params.position || {}, // (x, y) position pair\n    autoWidth: undefined, // width and height of nodes calculated by the renderer when set to special 'auto' value\n    autoHeight: undefined,\n    listeners: [], // array of bound listeners\n    group: group, // string; 'nodes' or 'edges'\n    style: {}, // properties as set by the style\n    rstyle: {}, // properties for style sent from the renderer to the core\n    styleCxts: [], // applied style contexts from the styler\n    removed: true, // whether it's inside the vis; true if removed (set true here since we call restore)\n    selected: params.selected ? true : false, // whether it's selected\n    selectable: params.selectable === undefined ? true : ( params.selectable ? true : false ), // whether it's selectable\n    locked: params.locked ? true : false, // whether the element is locked (cannot be moved)\n    grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately\n    grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), // whether the element can be grabbed\n    active: false, // whether the element is active from user interaction\n    classes: {}, // map ( className => true )\n    animation: { // object for currently-running animations\n      current: [],\n      queue: []\n    },\n    rscratch: {}, // object in which the renderer can store information\n    scratch: params.scratch || {}, // scratch objects\n    edges: [], // array of connected edges\n    children: [] // array of children\n  };\n\n  // renderedPosition overrides if specified\n  if( params.renderedPosition ){\n    var rpos = params.renderedPosition;\n    var pan = cy.pan();\n    var zoom = cy.zoom();\n\n    this._private.position = {\n      x: (rpos.x - pan.x)/zoom,\n      y: (rpos.y - pan.y)/zoom\n    };\n  }\n\n  if( is.string(params.classes) ){\n    var classes = params.classes.split(/\\s+/);\n    for( var i = 0, l = classes.length; i < l; i++ ){\n      var cls = classes[i];\n      if( !cls || cls === '' ){ continue; }\n\n      self._private.classes[cls] = true;\n    }\n  }\n\n  if( params.style || params.css ){\n    cy.style().applyBypass( this, params.style || params.css );\n  }\n\n  if( restore === undefined || restore ){\n    this.restore();\n  }\n\n};\n\nmodule.exports = Element;\n","'use strict';\n\nvar define = require('../define');\n\nvar elesfn = ({\n  on: define.on(), // .on( events [, selector] [, data], handler)\n  one: define.on({ unbindSelfOnTrigger: true }),\n  once: define.on({ unbindAllBindersOnTrigger: true }),\n  off: define.off(), // .off( events [, selector] [, handler] )\n  trigger: define.trigger(), // .trigger( events [, extraParams] )\n\n  rtrigger: function(event, extraParams){ // for internal use only\n    if( this.length === 0 ){ return; } // empty collections don't need to notify anything\n\n    // notify renderer\n    this.cy().notify({\n      type: event,\n      collection: this\n    });\n\n    this.trigger(event, extraParams);\n    return this;\n  }\n});\n\n// aliases:\ndefine.eventAliasesOn( elesfn );\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../is');\nvar Selector = require('../selector');\n\nvar elesfn = ({\n  nodes: function( selector ){\n    return this.filter(function(i, element){\n      return element.isNode();\n    }).filter(selector);\n  },\n\n  edges: function( selector ){\n    return this.filter(function(i, element){\n      return element.isEdge();\n    }).filter(selector);\n  },\n\n  filter: function( filter ){\n    if( is.fn(filter) ){\n      var elements = [];\n\n      for( var i = 0; i < this.length; i++ ){\n        var ele = this[i];\n\n        if( filter.apply(ele, [i, ele]) ){\n          elements.push(ele);\n        }\n      }\n\n      return this.spawn(elements);\n\n    } else if( is.string(filter) || is.elementOrCollection(filter) ){\n      return Selector(filter).filter(this);\n\n    } else if( filter === undefined ){\n      return this;\n    }\n\n    return this.spawn(); // if not handled by above, give 'em an empty collection\n  },\n\n  not: function( toRemove ){\n    if( !toRemove ){\n      return this;\n    } else {\n\n      if( is.string( toRemove ) ){\n        toRemove = this.filter( toRemove );\n      }\n\n      var elements = [];\n\n      for( var i = 0; i < this.length; i++ ){\n        var element = this[i];\n\n        var remove = toRemove._private.ids[ element.id() ];\n        if( !remove ){\n          elements.push( element );\n        }\n      }\n\n      return this.spawn( elements );\n    }\n\n  },\n\n  absoluteComplement: function(){\n    var cy = this._private.cy;\n\n    return cy.elements().not( this );\n  },\n\n  intersect: function( other ){\n    // if a selector is specified, then filter by it instead\n    if( is.string(other) ){\n      var selector = other;\n      return this.filter( selector );\n    }\n\n    var elements = [];\n    var col1 = this;\n    var col2 = other;\n    var col1Smaller = this.length < other.length;\n    // var ids1 = col1Smaller ? col1._private.ids : col2._private.ids;\n    var ids2 = col1Smaller ? col2._private.ids : col1._private.ids;\n    var col = col1Smaller ? col1 : col2;\n\n    for( var i = 0; i < col.length; i++ ){\n      var id = col[i]._private.data.id;\n      var ele = ids2[ id ];\n\n      if( ele ){\n        elements.push( ele );\n      }\n    }\n\n    return this.spawn( elements );\n  },\n\n  xor: function( other ){\n    var cy = this._private.cy;\n\n    if( is.string(other) ){\n      other = cy.$( other );\n    }\n\n    var elements = [];\n    var col1 = this;\n    var col2 = other;\n\n    var add = function( col, other ){\n\n      for( var i = 0; i < col.length; i++ ){\n        var ele = col[i];\n        var id = ele._private.data.id;\n        var inOther = other._private.ids[ id ];\n\n        if( !inOther ){\n          elements.push( ele );\n        }\n      }\n\n    };\n\n    add( col1, col2 );\n    add( col2, col1 );\n\n    return this.spawn( elements );\n  },\n\n  diff: function( other ){\n    var cy = this._private.cy;\n\n    if( is.string(other) ){\n      other = cy.$( other );\n    }\n\n    var left = [];\n    var right = [];\n    var both = [];\n    var col1 = this;\n    var col2 = other;\n\n    var add = function( col, other, retEles ){\n\n      for( var i = 0; i < col.length; i++ ){\n        var ele = col[i];\n        var id = ele._private.data.id;\n        var inOther = other._private.ids[ id ];\n\n        if( inOther ){\n          both.push( ele );\n        } else {\n          retEles.push( ele );\n        }\n      }\n\n    };\n\n    add( col1, col2, left );\n    add( col2, col1, right );\n\n    return {\n      left: this.spawn( left, { unique: true } ),\n      right: this.spawn( right, { unique: true } ),\n      both: this.spawn( both, { unique: true } )\n    };\n  },\n\n  add: function( toAdd ){\n    var cy = this._private.cy;\n\n    if( !toAdd ){\n      return this;\n    }\n\n    if( is.string(toAdd) ){\n      var selector = toAdd;\n      toAdd = cy.elements(selector);\n    }\n\n    var elements = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      elements.push( this[i] );\n    }\n\n    for( var i = 0; i < toAdd.length; i++ ){\n\n      var add = !this._private.ids[ toAdd[i].id() ];\n      if( add ){\n        elements.push( toAdd[i] );\n      }\n    }\n\n    return this.spawn(elements);\n  },\n\n  // in place merge on calling collection\n  merge: function( toAdd ){\n    var _p = this._private;\n    var cy = _p.cy;\n\n    if( !toAdd ){\n      return this;\n    }\n\n    if( is.string(toAdd) ){\n      var selector = toAdd;\n      toAdd = cy.elements(selector);\n    }\n\n    for( var i = 0; i < toAdd.length; i++ ){\n      var toAddEle = toAdd[i];\n      var id = toAddEle.id();\n      var add = !_p.ids[ id ];\n\n      if( add ){\n        var index = this.length++;\n\n        this[ index ] = toAddEle;\n        _p.ids[ id ] = toAddEle;\n        _p.indexes[ id ] = index;\n      }\n    }\n\n    return this; // chaining\n  },\n\n  // remove single ele in place in calling collection\n  unmergeOne: function( ele ){\n    ele = ele[0];\n\n    var _p = this._private;\n    var id = ele.id();\n    var i = _p.indexes[ id ];\n\n    if( i == null ){\n      return this; // no need to remove\n    }\n\n    // remove ele\n    this[i] = undefined;\n    _p.ids[ id ] = undefined;\n    _p.indexes[ id ] = undefined;\n\n    var unmergedLastEle = i === this.length - 1;\n\n    // replace empty spot with last ele in collection\n    if( this.length > 1 && !unmergedLastEle ){\n      var lastEleI = this.length - 1;\n      var lastEle = this[ lastEleI ];\n\n      this[ lastEleI ] = undefined;\n      this[i] = lastEle;\n      _p.indexes[ lastEle.id() ] = i;\n    }\n\n    // the collection is now 1 ele smaller\n    this.length--;\n\n    return this;\n  },\n\n  // remove eles in place on calling collection\n  unmerge: function( toRemove ){\n    var cy = this._private.cy;\n\n    if( !toRemove ){\n      return this;\n    }\n\n    if( is.string(toRemove) ){\n      var selector = toRemove;\n      toRemove = cy.elements(selector);\n    }\n\n    for( var i = 0; i < toRemove.length; i++ ){\n      this.unmergeOne( toRemove[i] );\n    }\n\n    return this; // chaining\n  },\n\n  map: function( mapFn, thisArg ){\n    var arr = [];\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var ret = thisArg ? mapFn.apply( thisArg, [ele, i, eles] ) : mapFn( ele, i, eles );\n\n      arr.push( ret );\n    }\n\n    return arr;\n  },\n\n  stdFilter: function( fn, thisArg ){\n    var filterEles = [];\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var include = thisArg ? fn.apply( thisArg, [ele, i, eles] ) : fn( ele, i, eles );\n\n      if( include ){\n        filterEles.push( ele );\n      }\n    }\n\n    return this.spawn( filterEles );\n  },\n\n  max: function( valFn, thisArg ){\n    var max = -Infinity;\n    var maxEle;\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );\n\n      if( val > max ){\n        max = val;\n        maxEle = ele;\n      }\n    }\n\n    return {\n      value: max,\n      ele: maxEle\n    };\n  },\n\n  min: function( valFn, thisArg ){\n    var min = Infinity;\n    var minEle;\n    var eles = this;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );\n\n      if( val < min ){\n        min = val;\n        minEle = ele;\n      }\n    }\n\n    return {\n      value: min,\n      ele: minEle\n    };\n  }\n});\n\n// aliases\nvar fn = elesfn;\nfn['u'] = fn['|'] = fn['+'] = fn.union = fn.or = fn.add;\nfn['\\\\'] = fn['!'] = fn['-'] = fn.difference = fn.relativeComplement = fn.subtract = fn.not;\nfn['n'] = fn['&'] = fn['.'] = fn.and = fn.intersection = fn.intersect;\nfn['^'] = fn['(+)'] = fn['(-)'] = fn.symmetricDifference = fn.symdiff = fn.xor;\nfn.fnFilter = fn.filterFn = fn.stdFilter;\nfn.complement = fn.abscomp = fn.absoluteComplement;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = ({\n  isNode: function(){\n    return this.group() === 'nodes';\n  },\n\n  isEdge: function(){\n    return this.group() === 'edges';\n  },\n\n  isLoop: function(){\n    return this.isEdge() && this.source().id() === this.target().id();\n  },\n\n  isSimple: function(){\n    return this.isEdge() && this.source().id() !== this.target().id();\n  },\n\n  group: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return ele._private.group;\n    }\n  }\n});\n\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar Element = require('./element');\n\n// factory for generating edge ids when no id is specified for a new element\nvar idFactory = {\n  prefix: 'ele',\n  id: 0,\n  generate: function(cy, element, tryThisId){\n    var json = is.element( element ) ? element._private : element;\n    var id = tryThisId != null ? tryThisId : this.prefix + this.id;\n\n    if( cy.getElementById(id).empty() ){\n      this.id++; // we've used the current id, so move it up\n    } else { // otherwise keep trying successive unused ids\n      while( !cy.getElementById(id).empty() ){\n        id = this.prefix + ( ++this.id );\n      }\n    }\n\n    return id;\n  }\n};\n\n// represents a set of nodes, edges, or both together\nvar Collection = function(cy, elements, options){\n  if( !(this instanceof Collection) ){\n    return new Collection(cy, elements, options);\n  }\n\n  if( cy === undefined || !is.core(cy) ){\n    util.error('A collection must have a reference to the core');\n    return;\n  }\n\n  var ids = {};\n  var indexes = {};\n  var createdElements = false;\n\n  if( !elements ){\n    elements = [];\n  } else if( elements.length > 0 && is.plainObject( elements[0] ) && !is.element( elements[0] ) ){\n    createdElements = true;\n\n    // make elements from json and restore all at once later\n    var eles = [];\n    var elesIds = {};\n\n    for( var i = 0, l = elements.length; i < l; i++ ){\n      var json = elements[i];\n\n      if( json.data == null ){\n        json.data = {};\n      }\n\n      var data = json.data;\n\n      // make sure newly created elements have valid ids\n      if( data.id == null ){\n        data.id = idFactory.generate( cy, json );\n      } else if( cy.getElementById( data.id ).length !== 0 || elesIds[ data.id ] ){\n        continue; // can't create element if prior id already exists\n      }\n\n      var ele = new Element( cy, json, false );\n      eles.push( ele );\n      elesIds[ data.id ] = true;\n    }\n\n    elements = eles;\n  }\n\n  this.length = 0;\n\n  for( var i = 0, l = elements.length; i < l; i++ ){\n    var element = elements[i];\n    if( !element ){  continue; }\n\n    var id = element._private.data.id;\n\n    if( !options || (options.unique && !ids[ id ] ) ){\n      ids[ id ] = element;\n      indexes[ id ] = this.length;\n\n      this[ this.length ] = element;\n      this.length++;\n    }\n  }\n\n  this._private = {\n    cy: cy,\n    ids: ids,\n    indexes: indexes\n  };\n\n  // restore the elements if we created them from json\n  if( createdElements ){\n    this.restore();\n  }\n};\n\n// Functions\n////////////////////////////////////////////////////////////////////////////////////////////////////\n\n// keep the prototypes in sync (an element has the same functions as a collection)\n// and use elefn and elesfn as shorthands to the prototypes\nvar elesfn = Element.prototype = Collection.prototype;\n\nelesfn.instanceString = function(){\n  return 'collection';\n};\n\nelesfn.spawn = function( cy, eles, opts ){\n  if( !is.core(cy) ){ // cy is optional\n    opts = eles;\n    eles = cy;\n    cy = this.cy();\n  }\n\n  return new Collection( cy, eles, opts );\n};\n\nelesfn.cy = function(){\n  return this._private.cy;\n};\n\nelesfn.element = function(){\n  return this[0];\n};\n\nelesfn.collection = function(){\n  if( is.collection(this) ){\n    return this;\n  } else { // an element\n    return new Collection( this._private.cy, [this] );\n  }\n};\n\nelesfn.unique = function(){\n  return new Collection( this._private.cy, this, { unique: true } );\n};\n\nelesfn.getElementById = function( id ){\n  var cy = this._private.cy;\n  var ele = this._private.ids[ id ];\n\n  return ele ? ele : new Collection(cy); // get ele or empty collection\n};\n\nelesfn.json = function( obj ){\n  var ele = this.element();\n  var cy = this.cy();\n\n  if( ele == null && obj ){ return this; } // can't set to no eles\n\n  if( ele == null ){ return undefined; } // can't get from no eles\n\n  var p = ele._private;\n\n  if( is.plainObject(obj) ){ // set\n\n    cy.startBatch();\n\n    if( obj.data ){\n      ele.data( obj.data );\n    }\n\n    if( obj.position ){\n      ele.position( obj.position );\n    }\n\n    // ignore group -- immutable\n\n    var checkSwitch = function( k, trueFnName, falseFnName ){\n      var obj_k = obj[k];\n\n      if( obj_k != null && obj_k !== p[k] ){\n        if( obj_k ){\n          ele[ trueFnName ]();\n        } else {\n          ele[ falseFnName ]();\n        }\n      }\n    };\n\n    checkSwitch( 'removed', 'remove', 'restore' );\n\n    checkSwitch( 'selected', 'select', 'unselect' );\n\n    checkSwitch( 'selectable', 'selectify', 'unselectify' );\n\n    checkSwitch( 'locked', 'lock', 'unlock' );\n\n    checkSwitch( 'grabbable', 'grabify', 'ungrabify' );\n\n    if( obj.classes != null ){\n      ele.classes( obj.classes );\n    }\n\n    cy.endBatch();\n\n    return this;\n\n  } else if( obj === undefined ){ // get\n\n    var json = {\n      data: util.copy( p.data ),\n      position: util.copy( p.position ),\n      group: p.group,\n      removed: p.removed,\n      selected: p.selected,\n      selectable: p.selectable,\n      locked: p.locked,\n      grabbable: p.grabbable,\n      classes: null\n    };\n\n    var classes = [];\n    for( var cls in p.classes ){\n      if( p.classes[cls] ){\n        classes.push(cls);\n      }\n    }\n    json.classes = classes.join(' ');\n\n    return json;\n  }\n};\n\nelesfn.jsons = function(){\n  var jsons = [];\n\n  for( var i = 0; i < this.length; i++ ){\n    var ele = this[i];\n    var json = ele.json();\n\n    jsons.push( json );\n  }\n\n  return jsons;\n};\n\nelesfn.clone = function(){\n  var cy = this.cy();\n  var elesArr = [];\n\n  for( var i = 0; i < this.length; i++ ){\n    var ele = this[i];\n    var json = ele.json();\n    var clone = new Element(cy, json, false); // NB no restore\n\n    elesArr.push( clone );\n  }\n\n  return new Collection( cy, elesArr );\n};\nelesfn.copy = elesfn.clone;\n\nelesfn.restore = function( notifyRenderer ){\n  var self = this;\n  var restored = [];\n  var cy = self.cy();\n\n  if( notifyRenderer === undefined ){\n    notifyRenderer = true;\n  }\n\n  // create arrays of nodes and edges, since we need to\n  // restore the nodes first\n  var elements = [];\n  var nodes = [], edges = [];\n  var numNodes = 0;\n  var numEdges = 0;\n  for( var i = 0, l = self.length; i < l; i++ ){\n    var ele = self[i];\n\n    // keep nodes first in the array and edges after\n    if( ele.isNode() ){ // put to front of array if node\n      nodes.push( ele );\n      numNodes++;\n    } else { // put to end of array if edge\n      edges.push( ele );\n      numEdges++;\n    }\n  }\n\n  elements = nodes.concat( edges );\n\n  // now, restore each element\n  for( var i = 0, l = elements.length; i < l; i++ ){\n    var ele = elements[i];\n\n    if( !ele.removed() ){\n      // don't need to do anything\n      continue;\n    }\n\n    var _private = ele._private;\n    var data = _private.data;\n\n    // set id and validate\n    if( data.id === undefined ){\n      data.id = idFactory.generate( cy, ele );\n\n    } else if( is.number(data.id) ){\n      data.id = '' + data.id; // now it's a string\n\n    } else if( is.emptyString(data.id) || !is.string(data.id) ){\n      util.error('Can not create element with invalid string ID `' + data.id + '`');\n\n      // can't create element if it has empty string as id or non-string id\n      continue;\n    } else if( cy.getElementById( data.id ).length !== 0 ){\n      util.error('Can not create second element with ID `' + data.id + '`');\n\n      // can't create element if one already has that id\n      continue;\n    }\n\n    var id = data.id; // id is finalised, now let's keep a ref\n\n    if( ele.isNode() ){ // extra checks for nodes\n      var node = ele;\n      var pos = _private.position;\n\n      // make sure the nodes have a defined position\n\n      if( pos.x == null ){\n        pos.x = 0;\n      }\n\n      if( pos.y == null ){\n        pos.y = 0;\n      }\n    }\n\n    if( ele.isEdge() ){ // extra checks for edges\n\n      var edge = ele;\n      var fields = ['source', 'target'];\n      var fieldsLength = fields.length;\n      var badSourceOrTarget = false;\n      for(var j = 0; j < fieldsLength; j++){\n\n        var field = fields[j];\n        var val = data[field];\n\n        if( is.number(val) ){\n          val = data[field] = '' + data[field]; // now string\n        }\n\n        if( val == null || val === '' ){\n          // can't create if source or target is not defined properly\n          util.error('Can not create edge `' + id + '` with unspecified ' + field);\n          badSourceOrTarget = true;\n        } else if( cy.getElementById(val).empty() ){\n          // can't create edge if one of its nodes doesn't exist\n          util.error('Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`');\n          badSourceOrTarget = true;\n        }\n      }\n\n      if( badSourceOrTarget ){ continue; } // can't create this\n\n      var src = cy.getElementById( data.source );\n      var tgt = cy.getElementById( data.target );\n\n      src._private.edges.push( edge );\n      tgt._private.edges.push( edge );\n\n      edge._private.source = src;\n      edge._private.target = tgt;\n\n    } // if is edge\n\n    // create mock ids map for element so it can be used like collections\n    _private.ids = {};\n    _private.ids[ id ] = ele;\n\n    _private.removed = false;\n    cy.addToPool( ele );\n\n    restored.push( ele );\n  } // for each element\n\n  // do compound node sanity checks\n  for( var i = 0; i < numNodes; i++ ){ // each node\n    var node = elements[i];\n    var data = node._private.data;\n\n    if( is.number(data.parent) ){ // then automake string\n      data.parent = '' + data.parent;\n    }\n\n    var parentId = data.parent;\n\n    var specifiedParent = parentId != null;\n\n    if( specifiedParent ){\n      var parent = cy.getElementById( parentId );\n\n      if( parent.empty() ){\n        // non-existant parent; just remove it\n        data.parent = undefined;\n      } else {\n        var selfAsParent = false;\n        var ancestor = parent;\n        while( !ancestor.empty() ){\n          if( node.same(ancestor) ){\n            // mark self as parent and remove from data\n            selfAsParent = true;\n            data.parent = undefined; // remove parent reference\n\n            // exit or we loop forever\n            break;\n          }\n\n          ancestor = ancestor.parent();\n        }\n\n        if( !selfAsParent ){\n          // connect with children\n          parent[0]._private.children.push( node );\n          node._private.parent = parent[0];\n\n          // let the core know we have a compound graph\n          cy._private.hasCompoundNodes = true;\n        }\n      } // else\n    } // if specified parent\n  } // for each node\n\n  restored = new Collection( cy, restored );\n  if( restored.length > 0 ){\n\n    var toUpdateStyle = restored.add( restored.connectedNodes() ).add( restored.parent() );\n    toUpdateStyle.updateStyle( notifyRenderer );\n\n    if( notifyRenderer ){\n      restored.rtrigger('add');\n    } else {\n      restored.trigger('add');\n    }\n  }\n\n  return self; // chainability\n};\n\nelesfn.removed = function(){\n  var ele = this[0];\n  return ele && ele._private.removed;\n};\n\nelesfn.inside = function(){\n  var ele = this[0];\n  return ele && !ele._private.removed;\n};\n\nelesfn.remove = function( notifyRenderer ){\n  var self = this;\n  var removed = [];\n  var elesToRemove = [];\n  var elesToRemoveIds = {};\n  var cy = self._private.cy;\n\n  if( notifyRenderer === undefined ){\n    notifyRenderer = true;\n  }\n\n  // add connected edges\n  function addConnectedEdges(node){\n    var edges = node._private.edges;\n    for( var i = 0; i < edges.length; i++ ){\n      add( edges[i] );\n    }\n  }\n\n\n  // add descendant nodes\n  function addChildren(node){\n    var children = node._private.children;\n\n    for( var i = 0; i < children.length; i++ ){\n      add( children[i] );\n    }\n  }\n\n  function add( ele ){\n    var alreadyAdded =  elesToRemoveIds[ ele.id() ];\n    if( alreadyAdded ){\n      return;\n    } else {\n      elesToRemoveIds[ ele.id() ] = true;\n    }\n\n    if( ele.isNode() ){\n      elesToRemove.push( ele ); // nodes are removed last\n\n      addConnectedEdges( ele );\n      addChildren( ele );\n    } else {\n      elesToRemove.unshift( ele ); // edges are removed first\n    }\n  }\n\n  // make the list of elements to remove\n  // (may be removing more than specified due to connected edges etc)\n\n  for( var i = 0, l = self.length; i < l; i++ ){\n    var ele = self[i];\n\n    add( ele );\n  }\n\n  function removeEdgeRef(node, edge){\n    var connectedEdges = node._private.edges;\n    for( var j = 0; j < connectedEdges.length; j++ ){\n      var connectedEdge = connectedEdges[j];\n\n      if( edge === connectedEdge ){\n        connectedEdges.splice( j, 1 );\n        break;\n      }\n    }\n  }\n\n  function removeChildRef(parent, ele){\n    ele = ele[0];\n    parent = parent[0];\n    var children = parent._private.children;\n\n    for( var j = 0; j < children.length; j++ ){\n      if( children[j][0] === ele[0] ){\n        children.splice(j, 1);\n        break;\n      }\n    }\n  }\n\n  for( var i = 0; i < elesToRemove.length; i++ ){\n    var ele = elesToRemove[i];\n\n    // mark as removed\n    ele._private.removed = true;\n\n    // remove from core pool\n    cy.removeFromPool( ele );\n\n    // add to list of removed elements\n    removed.push( ele );\n\n    if( ele.isEdge() ){ // remove references to this edge in its connected nodes\n      var src = ele.source()[0];\n      var tgt = ele.target()[0];\n\n      removeEdgeRef( src, ele );\n      removeEdgeRef( tgt, ele );\n\n    } else { // remove reference to parent\n      var parent = ele.parent();\n\n      if( parent.length !== 0 ){\n        removeChildRef(parent, ele);\n      }\n    }\n  }\n\n  // check to see if we have a compound graph or not\n  var elesStillInside = cy._private.elements;\n  cy._private.hasCompoundNodes = false;\n  for( var i = 0; i < elesStillInside.length; i++ ){\n    var ele = elesStillInside[i];\n\n    if( ele.isParent() ){\n      cy._private.hasCompoundNodes = true;\n      break;\n    }\n  }\n\n  var removedElements = new Collection( this.cy(), removed );\n  if( removedElements.size() > 0 ){\n    // must manually notify since trigger won't do this automatically once removed\n\n    if( notifyRenderer ){\n      this.cy().notify({\n        type: 'remove',\n        collection: removedElements\n      });\n    }\n\n    removedElements.trigger('remove');\n  }\n\n  // check for empty remaining parent nodes\n  var checkedParentId = {};\n  for( var i = 0; i < elesToRemove.length; i++ ){\n    var ele = elesToRemove[i];\n    var isNode = ele._private.group === 'nodes';\n    var parentId = ele._private.data.parent;\n\n    if( isNode && parentId !== undefined && !checkedParentId[ parentId ] ){\n      checkedParentId[ parentId ] = true;\n      var parent = cy.getElementById( parentId );\n\n      if( parent && parent.length !== 0 && !parent._private.removed && parent.children().length === 0 ){\n        parent.updateStyle();\n      }\n    }\n  }\n\n  return new Collection( cy, removed );\n};\n\nelesfn.move = function( struct ){\n  var cy = this._private.cy;\n\n  if( struct.source !== undefined || struct.target !== undefined ){\n    var srcId = struct.source;\n    var tgtId = struct.target;\n    var srcExists = cy.getElementById( srcId ).length > 0;\n    var tgtExists = cy.getElementById( tgtId ).length > 0;\n\n    if( srcExists || tgtExists ){\n      var jsons = this.jsons();\n\n      this.remove();\n\n      for( var i = 0; i < jsons.length; i++ ){\n        var json = jsons[i];\n\n        if( json.group === 'edges' ){\n          if( srcExists ){ json.data.source = srcId; }\n          if( tgtExists ){ json.data.target = tgtId; }\n        }\n      }\n\n      return cy.add( jsons );\n    }\n\n  } else if( struct.parent !== undefined ){ // move node to new parent\n    var parentId = struct.parent;\n    var parentExists = parentId === null || cy.getElementById( parentId ).length > 0;\n\n    if( parentExists ){\n      var jsons = this.jsons();\n      var descs = this.descendants();\n      var descsEtc = descs.merge( descs.add(this).connectedEdges() );\n\n      this.remove(); // NB: also removes descendants and their connected edges\n\n      for( var i = 0; i < this.length; i++ ){\n        var json = jsons[i];\n\n        if( json.group === 'nodes' ){\n          json.data.parent = parentId === null ? undefined : parentId;\n        }\n      }\n    }\n\n    return cy.add( jsons ).merge( descsEtc.restore() );\n  }\n\n  return this; // if nothing done\n};\n\n[\n  require('./algorithms'),\n  require('./animation'),\n  require('./class'),\n  require('./comparators'),\n  require('./compounds'),\n  require('./data'),\n  require('./degree'),\n  require('./dimensions'),\n  require('./events'),\n  require('./filter'),\n  require('./group'),\n  require('./index'),\n  require('./iteration'),\n  require('./layout'),\n  require('./style'),\n  require('./switch-functions'),\n  require('./traversing')\n].forEach(function( props ){\n  util.extend( elesfn, props );\n});\n\nmodule.exports = Collection;\n","'use strict';\n\nvar is = require('../is');\nvar zIndexSort = require('./zsort');\n\nvar elesfn = ({\n  each: function(fn){\n    if( is.fn(fn) ){\n      for(var i = 0; i < this.length; i++){\n        var ele = this[i];\n        var ret = fn.apply( ele, [ i, ele ] );\n\n        if( ret === false ){ break; } // exit each early on return false\n      }\n    }\n    return this;\n  },\n\n  forEach: function(fn, thisArg){\n    if( is.fn(fn) ){\n\n      for(var i = 0; i < this.length; i++){\n        var ele = this[i];\n        var ret = thisArg ? fn.apply( thisArg, [ ele, i, this ] ) : fn( ele, i, this );\n\n        if( ret === false ){ break; } // exit each early on return false\n      }\n    }\n\n    return this;\n  },\n\n  toArray: function(){\n    var array = [];\n\n    for(var i = 0; i < this.length; i++){\n      array.push( this[i] );\n    }\n\n    return array;\n  },\n\n  slice: function(start, end){\n    var array = [];\n    var thisSize = this.length;\n\n    if( end == null ){\n      end = thisSize;\n    }\n\n    if( start == null ){\n      start = 0;\n    }\n\n    if( start < 0 ){\n      start = thisSize + start;\n    }\n\n    if( end < 0 ){\n      end = thisSize + end;\n    }\n\n    for(var i = start; i >= 0 && i < end && i < thisSize; i++){\n      array.push( this[i] );\n    }\n\n    return this.spawn(array);\n  },\n\n  size: function(){\n    return this.length;\n  },\n\n  eq: function(i){\n    return this[i] || this.spawn();\n  },\n\n  first: function(){\n    return this[0] || this.spawn();\n  },\n\n  last: function(){\n    return this[ this.length - 1 ] || this.spawn();\n  },\n\n  empty: function(){\n    return this.length === 0;\n  },\n\n  nonempty: function(){\n    return !this.empty();\n  },\n\n  sort: function( sortFn ){\n    if( !is.fn( sortFn ) ){\n      return this;\n    }\n\n    var sorted = this.toArray().sort( sortFn );\n\n    return this.spawn(sorted);\n  },\n\n  sortByZIndex: function(){\n    return this.sort( zIndexSort );\n  },\n\n  zDepth: function(){\n    var ele = this[0];\n    if( !ele ){ return undefined; }\n\n    // var cy = ele.cy();\n    var _p = ele._private;\n    var group = _p.group;\n\n    if( group === 'nodes' ){\n      var depth = _p.data.parent ? ele.parents().size() : 0;\n\n      if( !ele.isParent() ){\n        return Number.MAX_VALUE; // childless nodes always on top\n      }\n\n      return depth;\n    } else {\n      var src = _p.source;\n      var tgt = _p.target;\n      var srcDepth = src.zDepth();\n      var tgtDepth = tgt.zDepth();\n\n      return Math.max( srcDepth, tgtDepth, 0 ); // depth of deepest parent\n    }\n  }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\n\nvar elesfn = ({\n\n  // using standard layout options, apply position function (w/ or w/o animation)\n  layoutPositions: function( layout, options, fn ){\n    var nodes = this.nodes();\n    var cy = this.cy();\n\n    layout.trigger({ type: 'layoutstart', layout: layout });\n\n    layout.animations = [];\n\n    if( options.animate ){\n      for( var i = 0; i < nodes.length; i++ ){\n        var node = nodes[i];\n        var lastNode = i === nodes.length - 1;\n\n        var newPos = fn.call( node, i, node );\n        var pos = node.position();\n\n        if( !is.number(pos.x) || !is.number(pos.y) ){\n          node.silentPosition({ x: 0, y: 0 });\n        }\n\n        var ani = node.animation({\n          position: newPos,\n          duration: options.animationDuration,\n          easing: options.animationEasing,\n          step: !lastNode ? undefined : function(){\n            if( options.fit ){\n              cy.fit( options.eles, options.padding );\n            }\n          },\n          complete: !lastNode ? undefined : function(){\n            if( options.zoom != null ){\n              cy.zoom( options.zoom );\n            }\n\n            if( options.pan ){\n              cy.pan( options.pan );\n            }\n\n            if( options.fit ){\n              cy.fit( options.eles, options.padding );\n            }\n\n            layout.one('layoutstop', options.stop);\n            layout.trigger({ type: 'layoutstop', layout: layout });\n          }\n        });\n\n        layout.animations.push( ani );\n\n        ani.play();\n      }\n\n      layout.one('layoutready', options.ready);\n      layout.trigger({ type: 'layoutready', layout: layout });\n    } else {\n      nodes.positions( fn );\n\n      if( options.fit ){\n        cy.fit( options.eles, options.padding );\n      }\n\n      if( options.zoom != null ){\n        cy.zoom( options.zoom );\n      }\n\n      if( options.pan ){\n        cy.pan( options.pan );\n      }\n\n      layout.one('layoutready', options.ready);\n      layout.trigger({ type: 'layoutready', layout: layout });\n\n      layout.one('layoutstop', options.stop);\n      layout.trigger({ type: 'layoutstop', layout: layout });\n    }\n\n    return this; // chaining\n  },\n\n  layout: function( options ){\n    var cy = this.cy();\n\n    cy.layout( util.extend({}, options, {\n      eles: this\n    }) );\n\n    return this;\n  },\n\n  makeLayout: function( options ){\n    var cy = this.cy();\n\n    return cy.makeLayout( util.extend({}, options, {\n      eles: this\n    }) );\n  }\n\n});\n\n// aliases:\nelesfn.createLayout = elesfn.makeLayout;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../is');\n\nvar elesfn = ({\n\n  // fully updates (recalculates) the style for the elements\n  updateStyle: function( notifyRenderer ){\n    var cy = this._private.cy;\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    if( cy._private.batchingStyle ){\n      var bEles = cy._private.batchStyleEles;\n\n      bEles.merge( this );\n\n      return this; // chaining and exit early when batching\n    }\n\n    var style = cy.style();\n    notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;\n\n    style.apply( this );\n\n    var updatedCompounds = this.updateCompoundBounds();\n    var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n\n    if( notifyRenderer ){\n      toNotify.rtrigger('style'); // let renderer know we changed style\n    } else {\n      toNotify.trigger('style'); // just fire the event\n    }\n    return this; // chaining\n  },\n\n  // just update the mappers in the elements' styles; cheaper than eles.updateStyle()\n  updateMappers: function( notifyRenderer ){\n    var cy = this._private.cy;\n    var style = cy.style();\n    notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    style.updateMappers( this );\n\n    var updatedCompounds = this.updateCompoundBounds();\n    var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n\n    if( notifyRenderer ){\n      toNotify.rtrigger('style'); // let renderer know we changed style\n    } else {\n      toNotify.trigger('style'); // just fire the event\n    }\n    return this; // chaining\n  },\n\n  // get the specified css property as a rendered value (i.e. on-screen value)\n  // or get the whole rendered style if no property specified (NB doesn't allow setting)\n  renderedCss: function( property ){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return this; }\n\n    var ele = this[0];\n\n    if( ele ){\n      var renstyle = ele.cy().style().getRenderedStyle( ele );\n\n      if( property === undefined ){\n        return renstyle;\n      } else {\n        return renstyle[ property ];\n      }\n    }\n  },\n\n  // read the calculated css style of the element or override the style (via a bypass)\n  css: function( name, value ){\n    var cy = this.cy();\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    var updateTransitions = false;\n    var style = cy.style();\n\n    if( is.plainObject(name) ){ // then extend the bypass\n      var props = name;\n      style.applyBypass( this, props, updateTransitions );\n\n      var updatedCompounds = this.updateCompoundBounds();\n      var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n      toNotify.rtrigger('style'); // let the renderer know we've updated style\n\n    } else if( is.string(name) ){\n\n      if( value === undefined ){ // then get the property from the style\n        var ele = this[0];\n\n        if( ele ){\n          return style.getStylePropertyValue( ele, name );\n        } else { // empty collection => can't get any value\n          return;\n        }\n\n      } else { // then set the bypass with the property value\n        style.applyBypass( this, name, value, updateTransitions );\n\n        var updatedCompounds = this.updateCompoundBounds();\n        var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n        toNotify.rtrigger('style'); // let the renderer know we've updated style\n      }\n\n    } else if( name === undefined ){\n      var ele = this[0];\n\n      if( ele ){\n        return style.getRawStyle( ele );\n      } else { // empty collection => can't get any value\n        return;\n      }\n    }\n\n    return this; // chaining\n  },\n\n  removeCss: function( names ){\n    var cy = this.cy();\n\n    if( !cy.styleEnabled() ){ return this; }\n\n    var updateTransitions = false;\n    var style = cy.style();\n    var eles = this;\n\n    if( names === undefined ){\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        style.removeAllBypasses( ele, updateTransitions );\n      }\n    } else {\n      names = names.split(/\\s+/);\n\n      for( var i = 0; i < eles.length; i++ ){\n        var ele = eles[i];\n\n        style.removeBypasses( ele, names, updateTransitions );\n      }\n    }\n\n    var updatedCompounds = this.updateCompoundBounds();\n    var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n    toNotify.rtrigger('style'); // let the renderer know we've updated style\n\n    return this; // chaining\n  },\n\n  show: function(){\n    this.css('display', 'element');\n    return this; // chaining\n  },\n\n  hide: function(){\n    this.css('display', 'none');\n    return this; // chaining\n  },\n\n  visible: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return true; }\n\n    var ele = this[0];\n    var hasCompoundNodes = cy.hasCompoundNodes();\n\n    if( ele ){\n      var style = ele._private.style;\n\n      if(\n        style['visibility'].value !== 'visible'\n        || style['display'].value !== 'element'\n      ){\n        return false;\n      }\n\n      if( ele._private.group === 'nodes' ){\n        if( !hasCompoundNodes ){ return true; }\n\n        var parents = ele._private.data.parent ? ele.parents() : null;\n\n        if( parents ){\n          for( var i = 0; i < parents.length; i++ ){\n            var parent = parents[i];\n            var pStyle = parent._private.style;\n            var pVis = pStyle['visibility'].value;\n            var pDis = pStyle['display'].value;\n\n            if( pVis !== 'visible' || pDis !== 'element' ){\n              return false;\n            }\n          }\n        }\n\n        return true;\n      } else {\n        var src = ele._private.source;\n        var tgt = ele._private.target;\n\n        return src.visible() && tgt.visible();\n      }\n\n    }\n  },\n\n  hidden: function(){\n    var ele = this[0];\n\n    if( ele ){\n      return !ele.visible();\n    }\n  },\n\n  effectiveOpacity: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return 1; }\n\n    var hasCompoundNodes = cy.hasCompoundNodes();\n    var ele = this[0];\n\n    if( ele ){\n      var _p = ele._private;\n      var parentOpacity = _p.style.opacity.value;\n\n      if( !hasCompoundNodes ){ return parentOpacity; }\n\n      var parents = !_p.data.parent ? null : ele.parents();\n\n      if( parents ){\n        for( var i = 0; i < parents.length; i++ ){\n          var parent = parents[i];\n          var opacity = parent._private.style.opacity.value;\n\n          parentOpacity = opacity * parentOpacity;\n        }\n      }\n\n      return parentOpacity;\n    }\n  },\n\n  transparent: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return false; }\n\n    var ele = this[0];\n    var hasCompoundNodes = ele.cy().hasCompoundNodes();\n\n    if( ele ){\n      if( !hasCompoundNodes ){\n        return ele._private.style.opacity.value === 0;\n      } else {\n        return ele.effectiveOpacity() === 0;\n      }\n    }\n  },\n\n  isFullAutoParent: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return false; }\n\n    var ele = this[0];\n\n    if( ele ){\n      var autoW = ele._private.style['width'].value === 'auto';\n      var autoH = ele._private.style['height'].value === 'auto';\n\n      return ele.isParent() && autoW && autoH;\n    }\n  },\n\n  backgrounding: function(){\n    var cy = this.cy();\n    if( !cy.styleEnabled() ){ return false; }\n\n    var ele = this[0];\n\n    return ele._private.backgrounding ? true : false;\n  }\n\n});\n\n\nelesfn.bypass = elesfn.style = elesfn.css;\nelesfn.renderedStyle = elesfn.renderedCss;\nelesfn.removeBypass = elesfn.removeStyle = elesfn.removeCss;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = {};\n\nfunction defineSwitchFunction(params){\n  return function(){\n    var args = arguments;\n    var changedEles = [];\n\n    // e.g. cy.nodes().select( data, handler )\n    if( args.length === 2 ){\n      var data = args[0];\n      var handler = args[1];\n      this.bind( params.event, data, handler );\n    }\n\n    // e.g. cy.nodes().select( handler )\n    else if( args.length === 1 ){\n      var handler = args[0];\n      this.bind( params.event, handler );\n    }\n\n    // e.g. cy.nodes().select()\n    else if( args.length === 0 ){\n      for( var i = 0; i < this.length; i++ ){\n        var ele = this[i];\n        var able = !params.ableField || ele._private[params.ableField];\n        var changed = ele._private[params.field] != params.value;\n\n        if( params.overrideAble ){\n          var overrideAble = params.overrideAble(ele);\n\n          if( overrideAble !== undefined ){\n            able = overrideAble;\n\n            if( !overrideAble ){ return this; } // to save cycles assume not able for all on override\n          }\n        }\n\n        if( able ){\n          ele._private[params.field] = params.value;\n\n          if( changed ){\n            changedEles.push( ele );\n          }\n        }\n      }\n\n      var changedColl = this.spawn( changedEles );\n      changedColl.updateStyle(); // change of state => possible change of style\n      changedColl.trigger( params.event );\n    }\n\n    return this;\n  };\n}\n\nfunction defineSwitchSet( params ){\n  elesfn[ params.field ] = function(){\n    var ele = this[0];\n\n    if( ele ){\n      if( params.overrideField ){\n        var val = params.overrideField(ele);\n\n        if( val !== undefined ){\n          return val;\n        }\n      }\n\n      return ele._private[ params.field ];\n    }\n  };\n\n  elesfn[ params.on ] = defineSwitchFunction({\n    event: params.on,\n    field: params.field,\n    ableField: params.ableField,\n    overrideAble: params.overrideAble,\n    value: true\n  });\n\n  elesfn[ params.off ] = defineSwitchFunction({\n    event: params.off,\n    field: params.field,\n    ableField: params.ableField,\n    overrideAble: params.overrideAble,\n    value: false\n  });\n}\n\ndefineSwitchSet({\n  field: 'locked',\n  overrideField: function(ele){\n    return ele.cy().autolock() ? true : undefined;\n  },\n  on: 'lock',\n  off: 'unlock'\n});\n\ndefineSwitchSet({\n  field: 'grabbable',\n  overrideField: function(ele){\n    return ele.cy().autoungrabify() ? false : undefined;\n  },\n  on: 'grabify',\n  off: 'ungrabify'\n});\n\ndefineSwitchSet({\n  field: 'selected',\n  ableField: 'selectable',\n  overrideAble: function(ele){\n    return ele.cy().autounselectify() ? false : undefined;\n  },\n  on: 'select',\n  off: 'unselect'\n});\n\ndefineSwitchSet({\n  field: 'selectable',\n  overrideField: function(ele){\n    return ele.cy().autounselectify() ? false : undefined;\n  },\n  on: 'selectify',\n  off: 'unselectify'\n});\n\nelesfn.deselect = elesfn.unselect;\n\nelesfn.grabbed = function(){\n  var ele = this[0];\n  if( ele ){\n    return ele._private.grabbed;\n  }\n};\n\ndefineSwitchSet({\n  field: 'active',\n  on: 'activate',\n  off: 'unactivate'\n});\n\nelesfn.inactive = function(){\n  var ele = this[0];\n  if( ele ){\n    return !ele._private.active;\n  }\n};\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar elesfn = {};\n\nutil.extend(elesfn, {\n  // get the root nodes in the DAG\n  roots: function( selector ){\n    var eles = this;\n    var roots = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      if( !ele.isNode() ){\n        continue;\n      }\n\n      var hasEdgesPointingIn = ele.connectedEdges(function(){\n        return this.data('target') === ele.id() && this.data('source') !== ele.id();\n      }).length > 0;\n\n      if( !hasEdgesPointingIn ){\n        roots.push( ele );\n      }\n    }\n\n    return this.spawn( roots, { unique: true } ).filter( selector );\n  },\n\n  // get the leaf nodes in the DAG\n  leaves: function( selector ){\n    var eles = this;\n    var leaves = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      if( !ele.isNode() ){\n        continue;\n      }\n\n      var hasEdgesPointingOut = ele.connectedEdges(function(){\n        return this.data('source') === ele.id() && this.data('target') !== ele.id();\n      }).length > 0;\n\n      if( !hasEdgesPointingOut ){\n        leaves.push( ele );\n      }\n    }\n\n    return this.spawn( leaves, { unique: true } ).filter( selector );\n  },\n\n  // normally called children in graph theory\n  // these nodes =edges=> outgoing nodes\n  outgoers: function( selector ){\n    var eles = this;\n    var oEles = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var eleId = ele.id();\n\n      if( !ele.isNode() ){ continue; }\n\n      var edges = ele._private.edges;\n      for( var j = 0; j < edges.length; j++ ){\n        var edge = edges[j];\n        var srcId = edge._private.data.source;\n        var tgtId = edge._private.data.target;\n\n        if( srcId === eleId && tgtId !== eleId ){\n          oEles.push( edge );\n          oEles.push( edge.target()[0] );\n        }\n      }\n    }\n\n    return this.spawn( oEles, { unique: true } ).filter( selector );\n  },\n\n  // aka DAG descendants\n  successors: function( selector ){\n    var eles = this;\n    var sEles = [];\n    var sElesIds = {};\n\n    for(;;){\n      var outgoers = eles.outgoers();\n\n      if( outgoers.length === 0 ){ break; } // done if no outgoers left\n\n      var newOutgoers = false;\n      for( var i = 0; i < outgoers.length; i++ ){\n        var outgoer = outgoers[i];\n        var outgoerId = outgoer.id();\n\n        if( !sElesIds[ outgoerId ] ){\n          sElesIds[ outgoerId ] = true;\n          sEles.push( outgoer );\n          newOutgoers = true;\n        }\n      }\n\n      if( !newOutgoers ){ break; } // done if touched all outgoers already\n\n      eles = outgoers;\n    }\n\n    return this.spawn( sEles, { unique: true } ).filter( selector );\n  },\n\n  // normally called parents in graph theory\n  // these nodes <=edges= incoming nodes\n  incomers: function( selector ){\n    var eles = this;\n    var oEles = [];\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n      var eleId = ele.id();\n\n      if( !ele.isNode() ){ continue; }\n\n      var edges = ele._private.edges;\n      for( var j = 0; j < edges.length; j++ ){\n        var edge = edges[j];\n        var srcId = edge._private.data.source;\n        var tgtId = edge._private.data.target;\n\n        if( tgtId === eleId && srcId !== eleId ){\n          oEles.push( edge );\n          oEles.push( edge.source()[0] );\n        }\n      }\n    }\n\n    return this.spawn( oEles, { unique: true } ).filter( selector );\n  },\n\n  // aka DAG ancestors\n  predecessors: function( selector ){\n    var eles = this;\n    var pEles = [];\n    var pElesIds = {};\n\n    for(;;){\n      var incomers = eles.incomers();\n\n      if( incomers.length === 0 ){ break; } // done if no incomers left\n\n      var newIncomers = false;\n      for( var i = 0; i < incomers.length; i++ ){\n        var incomer = incomers[i];\n        var incomerId = incomer.id();\n\n        if( !pElesIds[ incomerId ] ){\n          pElesIds[ incomerId ] = true;\n          pEles.push( incomer );\n          newIncomers = true;\n        }\n      }\n\n      if( !newIncomers ){ break; } // done if touched all incomers already\n\n      eles = incomers;\n    }\n\n    return this.spawn( pEles, { unique: true } ).filter( selector );\n  }\n});\n\n\n// Neighbourhood functions\n//////////////////////////\n\nutil.extend(elesfn, {\n  neighborhood: function(selector){\n    var elements = [];\n    var nodes = this.nodes();\n\n    for( var i = 0; i < nodes.length; i++ ){ // for all nodes\n      var node = nodes[i];\n      var connectedEdges = node.connectedEdges();\n\n      // for each connected edge, add the edge and the other node\n      for( var j = 0; j < connectedEdges.length; j++ ){\n        var edge = connectedEdges[j];\n        var src = edge._private.source;\n        var tgt = edge._private.target;\n        var otherNode = node === src ? tgt : src;\n\n        // need check in case of loop\n        if( otherNode.length > 0 ){\n          elements.push( otherNode[0] ); // add node 1 hop away\n        }\n\n        // add connected edge\n        elements.push( edge[0] );\n      }\n\n    }\n\n    return ( this.spawn( elements, { unique: true } ) ).filter( selector );\n  },\n\n  closedNeighborhood: function(selector){\n    return this.neighborhood().add( this ).filter( selector );\n  },\n\n  openNeighborhood: function(selector){\n    return this.neighborhood( selector );\n  }\n});\n\n// aliases\nelesfn.neighbourhood = elesfn.neighborhood;\nelesfn.closedNeighbourhood = elesfn.closedNeighborhood;\nelesfn.openNeighbourhood = elesfn.openNeighborhood;\n\n// Edge functions\n/////////////////\n\nutil.extend(elesfn, {\n  source: function( selector ){\n    var ele = this[0];\n    var src;\n\n    if( ele ){\n      src = ele._private.source;\n    }\n\n    return src && selector ? src.filter( selector ) : src;\n  },\n\n  target: function( selector ){\n    var ele = this[0];\n    var tgt;\n\n    if( ele ){\n      tgt = ele._private.target;\n    }\n\n    return tgt && selector ? tgt.filter( selector ) : tgt;\n  },\n\n  sources: defineSourceFunction({\n    attr: 'source'\n  }),\n\n  targets: defineSourceFunction({\n    attr: 'target'\n  })\n});\n\nfunction defineSourceFunction( params ){\n  return function( selector ){\n    var sources = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      var ele = this[i];\n      var src = ele._private[ params.attr ];\n\n      if( src ){\n        sources.push( src );\n      }\n    }\n\n    return this.spawn( sources, { unique: true } ).filter( selector );\n  };\n}\n\nutil.extend(elesfn, {\n  edgesWith: defineEdgesWithFunction(),\n\n  edgesTo: defineEdgesWithFunction({\n    thisIs: 'source'\n  })\n});\n\nfunction defineEdgesWithFunction( params ){\n\n  return function edgesWithImpl( otherNodes ){\n    var elements = [];\n    var cy = this._private.cy;\n    var p = params || {};\n\n    // get elements if a selector is specified\n    if( is.string(otherNodes) ){\n      otherNodes = cy.$( otherNodes );\n    }\n\n    var thisIds = this._private.ids;\n    var otherIds = otherNodes._private.ids;\n\n    for( var h = 0; h < otherNodes.length; h++ ){\n      var edges = otherNodes[h]._private.edges;\n\n      for( var i = 0; i < edges.length; i++ ){\n        var edge = edges[i];\n        var edgeData = edge._private.data;\n        var thisToOther = thisIds[ edgeData.source ] && otherIds[ edgeData.target ];\n        var otherToThis = otherIds[ edgeData.source ] && thisIds[ edgeData.target ];\n        var edgeConnectsThisAndOther = thisToOther || otherToThis;\n\n        if( !edgeConnectsThisAndOther ){ continue; }\n\n        if( p.thisIs ){\n          if( p.thisIs === 'source' && !thisToOther ){ continue; }\n\n          if( p.thisIs === 'target' && !otherToThis ){ continue; }\n        }\n\n        elements.push( edge );\n      }\n    }\n\n    return this.spawn( elements, { unique: true } );\n  };\n}\n\nutil.extend(elesfn, {\n  connectedEdges: function( selector ){\n    var retEles = [];\n\n    var eles = this;\n    for( var i = 0; i < eles.length; i++ ){\n      var node = eles[i];\n      if( !node.isNode() ){ continue; }\n\n      var edges = node._private.edges;\n\n      for( var j = 0; j < edges.length; j++ ){\n        var edge = edges[j];\n        retEles.push( edge );\n      }\n    }\n\n    return this.spawn( retEles, { unique: true } ).filter( selector );\n  },\n\n  connectedNodes: function( selector ){\n    var retEles = [];\n\n    var eles = this;\n    for( var i = 0; i < eles.length; i++ ){\n      var edge = eles[i];\n      if( !edge.isEdge() ){ continue; }\n\n      retEles.push( edge.source()[0] );\n      retEles.push( edge.target()[0] );\n    }\n\n    return this.spawn( retEles, { unique: true } ).filter( selector );\n  },\n\n  parallelEdges: defineParallelEdgesFunction(),\n\n  codirectedEdges: defineParallelEdgesFunction({\n    codirected: true\n  })\n});\n\nfunction defineParallelEdgesFunction(params){\n  var defaults = {\n    codirected: false\n  };\n  params = util.extend({}, defaults, params);\n\n  return function( selector ){\n    var elements = [];\n    var edges = this.edges();\n    var p = params;\n\n    // look at all the edges in the collection\n    for( var i = 0; i < edges.length; i++ ){\n      var edge1 = edges[i];\n      var src1 = edge1.source()[0];\n      var srcid1 = src1.id();\n      var tgt1 = edge1.target()[0];\n      var tgtid1 = tgt1.id();\n      var srcEdges1 = src1._private.edges;\n\n      // look at edges connected to the src node of this edge\n      for( var j = 0; j < srcEdges1.length; j++ ){\n        var edge2 = srcEdges1[j];\n        var edge2data = edge2._private.data;\n        var tgtid2 = edge2data.target;\n        var srcid2 = edge2data.source;\n\n        var codirected = tgtid2 === tgtid1 && srcid2 === srcid1;\n        var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2;\n\n        if( (p.codirected && codirected) || (!p.codirected && (codirected || oppdirected)) ){\n          elements.push( edge2 );\n        }\n      }\n    }\n\n    return this.spawn( elements, { unique: true } ).filter( selector );\n  };\n\n}\n\n// Misc functions\n/////////////////\n\nutil.extend(elesfn, {\n  components: function(){\n    var cy = this.cy();\n    var visited = cy.collection();\n    var unvisited = this.nodes();\n    var components = [];\n\n    var visitInComponent = function( node, component ){\n      visited.merge( node );\n      unvisited.unmerge( node );\n      component.merge( node );\n    };\n\n    do {\n      var component = cy.collection();\n      components.push( component );\n\n      var root = unvisited[0];\n      visitInComponent( root, component );\n\n      this.bfs({\n        directed: false,\n        roots: root,\n        visit: function( i, depth, v, e, u ){\n          visitInComponent( v, component );\n        }\n      });\n\n    } while( unvisited.length > 0 );\n\n    return components.map(function( component ){\n      return component.closedNeighborhood(); // add the edges\n    });\n  }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar zIndexSort = function( a, b ){\n  var cy = a.cy();\n  var a_p = a._private;\n  var b_p = b._private;\n  var zDiff = a_p.style['z-index'].value - b_p.style['z-index'].value;\n  var depthA = 0;\n  var depthB = 0;\n  var hasCompoundNodes = cy.hasCompoundNodes();\n  var aIsNode = a_p.group === 'nodes';\n  var aIsEdge = a_p.group === 'edges';\n  var bIsNode = b_p.group === 'nodes';\n  var bIsEdge = b_p.group === 'edges';\n\n  // no need to calculate element depth if there is no compound node\n  if( hasCompoundNodes ){\n    depthA = a.zDepth();\n    depthB = b.zDepth();\n  }\n\n  var depthDiff = depthA - depthB;\n  var sameDepth = depthDiff === 0;\n\n  if( sameDepth ){\n\n    if( aIsNode && bIsEdge ){\n      return 1; // 'a' is a node, it should be drawn later\n\n    } else if( aIsEdge && bIsNode ){\n      return -1; // 'a' is an edge, it should be drawn first\n\n    } else { // both nodes or both edges\n      if( zDiff === 0 ){ // same z-index => compare indices in the core (order added to graph w/ last on top)\n        return a_p.index - b_p.index;\n      } else {\n        return zDiff;\n      }\n    }\n\n  // elements on different level\n  } else {\n    return depthDiff; // deeper element should be drawn later\n  }\n\n};\n\nmodule.exports = zIndexSort;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\nvar Collection = require('../collection');\nvar Element = require('../collection/element');\nvar window = require('../window');\nvar document = window ? window.document : null;\nvar NullRenderer = require('../extensions/renderer/null');\n\nvar corefn = {\n  add: function(opts){\n\n    var elements;\n    var cy = this;\n\n    // add the elements\n    if( is.elementOrCollection(opts) ){\n      var eles = opts;\n\n      if( eles._private.cy === cy ){ // same instance => just restore\n        elements = eles.restore();\n\n      } else { // otherwise, copy from json\n        var jsons = [];\n\n        for( var i = 0; i < eles.length; i++ ){\n          var ele = eles[i];\n          jsons.push( ele.json() );\n        }\n\n        elements = new Collection( cy, jsons );\n      }\n    }\n\n    // specify an array of options\n    else if( is.array(opts) ){\n      var jsons = opts;\n\n      elements = new Collection(cy, jsons);\n    }\n\n    // specify via opts.nodes and opts.edges\n    else if( is.plainObject(opts) && (is.array(opts.nodes) || is.array(opts.edges)) ){\n      var elesByGroup = opts;\n      var jsons = [];\n\n      var grs = ['nodes', 'edges'];\n      for( var i = 0, il = grs.length; i < il; i++ ){\n        var group = grs[i];\n        var elesArray = elesByGroup[group];\n\n        if( is.array(elesArray) ){\n\n          for( var j = 0, jl = elesArray.length; j < jl; j++ ){\n            var json = util.extend( { group: group }, elesArray[j] );\n\n            jsons.push( json );\n          }\n        }\n      }\n\n      elements = new Collection(cy, jsons);\n    }\n\n    // specify options for one element\n    else {\n      var json = opts;\n      elements = (new Element( cy, json )).collection();\n    }\n\n    return elements;\n  },\n\n  remove: function(collection){\n    if( is.elementOrCollection(collection) ){\n      collection = collection;\n    } else if( is.string(collection) ){\n      var selector = collection;\n      collection = this.$( selector );\n    }\n\n    return collection.remove();\n  },\n\n  load: function(elements, onload, ondone){\n    var cy = this;\n\n    cy.notifications(false);\n\n    // remove old elements\n    var oldEles = cy.elements();\n    if( oldEles.length > 0 ){\n      oldEles.remove();\n    }\n\n    if( elements != null ){\n      if( is.plainObject(elements) || is.array(elements) ){\n        cy.add( elements );\n      }\n    }\n\n    cy.one('layoutready', function(e){\n      cy.notifications(true);\n      cy.trigger(e); // we missed this event by turning notifications off, so pass it on\n\n      cy.notify({\n        type: 'load',\n        collection: cy.elements()\n      });\n\n      cy.one('load', onload);\n      cy.trigger('load');\n    }).one('layoutstop', function(){\n      cy.one('done', ondone);\n      cy.trigger('done');\n    });\n\n    var layoutOpts = util.extend({}, cy._private.options.layout);\n    layoutOpts.eles = cy.$();\n\n    cy.layout( layoutOpts );\n\n    return this;\n  }\n};\n\nmodule.exports = corefn;\n","'use strict';\n\nvar define = require('../define');\nvar util = require('../util');\nvar is = require('../is');\n\nvar corefn = ({\n\n  // pull in animation functions\n  animate: define.animate(),\n  animation: define.animation(),\n  animated: define.animated(),\n  clearQueue: define.clearQueue(),\n  delay: define.delay(),\n  delayAnimation: define.delayAnimation(),\n  stop: define.stop(),\n\n  addToAnimationPool: function( eles ){\n    var cy = this;\n\n    if( !cy.styleEnabled() ){ return; } // save cycles when no style used\n\n    cy._private.aniEles.merge( eles );\n  },\n\n  stopAnimationLoop: function(){\n    this._private.animationsRunning = false;\n  },\n\n  startAnimationLoop: function(){\n    var cy = this;\n\n    cy._private.animationsRunning = true;\n\n    if( !cy.styleEnabled() ){ return; } // save cycles when no style used\n\n    // NB the animation loop will exec in headless environments if style enabled\n    // and explicit cy.destroy() is necessary to stop the loop\n\n    function globalAnimationStep(){\n      if( !cy._private.animationsRunning ){ return; }\n\n      util.requestAnimationFrame(function(now){\n        handleElements(now);\n        globalAnimationStep();\n      });\n    }\n\n    globalAnimationStep(); // first call\n\n    function handleElements( now ){\n      var eles = cy._private.aniEles;\n      var doneEles = [];\n\n      function handleElement( ele, isCore ){\n        var _p = ele._private;\n        var current = _p.animation.current;\n        var queue = _p.animation.queue;\n        var ranAnis = false;\n\n        // if nothing currently animating, get something from the queue\n        if( current.length === 0 ){\n          var next = queue.shift();\n\n          if( next ){\n            current.push( next );\n          }\n        }\n\n        var callbacks = function( callbacks ){\n          for( var j = callbacks.length - 1; j >= 0; j-- ){\n            var cb = callbacks[j];\n\n            cb();\n          }\n\n          callbacks.splice( 0, callbacks.length );\n        };\n\n        // step and remove if done\n        for( var i = current.length - 1; i >= 0; i-- ){\n          var ani = current[i];\n          var ani_p = ani._private;\n\n          if( ani_p.stopped ){\n            current.splice( i, 1 );\n\n            ani_p.hooked = false;\n            ani_p.playing = false;\n            ani_p.started = false;\n\n            callbacks( ani_p.frames );\n\n            continue;\n          }\n\n          if( !ani_p.playing && !ani_p.applying ){ continue; }\n\n          // an apply() while playing shouldn't do anything\n          if( ani_p.playing && ani_p.applying ){\n            ani_p.applying = false;\n          }\n\n          if( !ani_p.started ){\n            startAnimation( ele, ani, now );\n          }\n\n          step( ele, ani, now, isCore );\n\n          if( ani_p.applying ){\n            ani_p.applying = false;\n          }\n\n          callbacks( ani_p.frames );\n\n          if( ani.completed() ){\n            current.splice(i, 1);\n\n            ani_p.hooked = false;\n            ani_p.playing = false;\n            ani_p.started = false;\n\n            callbacks( ani_p.completes );\n          }\n\n          ranAnis = true;\n        }\n\n        if( !isCore && current.length === 0 && queue.length === 0 ){\n          doneEles.push( ele );\n        }\n\n        return ranAnis;\n      } // handleElement\n\n      // handle all eles\n      var ranEleAni = false;\n      for( var e = 0; e < eles.length; e++ ){\n        var ele = eles[e];\n        var handledThisEle = handleElement( ele );\n\n        ranEleAni = ranEleAni || handledThisEle;\n      } // each element\n\n      var ranCoreAni = handleElement( cy, true );\n\n      // notify renderer\n      if( ranEleAni || ranCoreAni ){\n        var toNotify;\n\n        if( eles.length > 0 ){\n          var updatedEles = eles.updateCompoundBounds();\n          toNotify = updatedEles.length > 0 ? eles.add( updatedEles ) : eles;\n        }\n\n        cy.notify({\n          type: 'draw',\n          collection: toNotify\n        });\n      }\n\n      // remove elements from list of currently animating if its queues are empty\n      eles.unmerge( doneEles );\n\n    } // handleElements\n\n    function startAnimation( self, ani, now ){\n      var isCore = is.core( self );\n      var isEles = !isCore;\n      var ele = self;\n      var style = cy._private.style;\n      var ani_p = ani._private;\n\n      if( isEles ){\n        var pos = ele._private.position;\n\n        ani_p.startPosition = ani_p.startPosition || {\n          x: pos.x,\n          y: pos.y\n        };\n\n        ani_p.startStyle = ani_p.startStyle || style.getValueStyle( ele );\n      }\n\n      if( isCore ){\n        var pan = cy._private.pan;\n\n        ani_p.startPan = ani_p.startPan || {\n          x: pan.x,\n          y: pan.y\n        };\n\n        ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom;\n      }\n\n      ani_p.started = true;\n      ani_p.startTime = now - ani_p.progress * ani_p.duration;\n    }\n\n    function step( self, ani, now, isCore ){\n      var style = cy._private.style;\n      var isEles = !isCore;\n      var _p = self._private;\n      var ani_p = ani._private;\n      var pEasing = ani_p.easing;\n      var startTime = ani_p.startTime;\n\n      if( !ani_p.easingImpl ){\n\n        if( pEasing == null ){ // use default\n          ani_p.easingImpl = easings['linear'];\n\n        } else { // then define w/ name\n          var easingVals;\n\n          if( is.string( pEasing ) ){\n            var easingProp = style.parse('transition-timing-function', pEasing);\n\n            easingVals = easingProp.value;\n\n          } else { // then assume preparsed array\n            easingVals = pEasing;\n          }\n\n          var name, args;\n\n          if( is.string( easingVals ) ){\n            name = easingVals;\n            args = [];\n          } else {\n            name = easingVals[1];\n            args = easingVals.slice(2).map(function(n){ return +n; });\n          }\n\n          if( args.length > 0 ){ // create with args\n            if( name === 'spring' ){\n              args.push( ani_p.duration ); // need duration to generate spring\n            }\n\n            ani_p.easingImpl = easings[ name ].apply( null, args );\n          } else { // static impl by name\n            ani_p.easingImpl = easings[ name ];\n          }\n        }\n\n      }\n\n      var easing = ani_p.easingImpl;\n      var percent;\n\n      if( ani_p.duration === 0 ){\n        percent = 1;\n      } else {\n        percent = (now - startTime) / ani_p.duration;\n      }\n\n      if( ani_p.applying ){\n        percent = ani_p.progress;\n      }\n\n      if( percent < 0 ){\n        percent = 0;\n      } else if( percent > 1 ){\n        percent = 1;\n      }\n\n      if( ani_p.delay == null ){ // then update\n\n        var startPos = ani_p.startPosition;\n        var endPos = ani_p.position;\n        var pos = _p.position;\n        if( endPos && isEles ){\n          if( valid( startPos.x, endPos.x ) ){\n            pos.x = ease( startPos.x, endPos.x, percent, easing );\n          }\n\n          if( valid( startPos.y, endPos.y ) ){\n            pos.y = ease( startPos.y, endPos.y, percent, easing );\n          }\n        }\n\n        var startPan = ani_p.startPan;\n        var endPan = ani_p.pan;\n        var pan = _p.pan;\n        var animatingPan = endPan != null && isCore;\n        if( animatingPan ){\n          if( valid( startPan.x, endPan.x ) ){\n            pan.x = ease( startPan.x, endPan.x, percent, easing );\n          }\n\n          if( valid( startPan.y, endPan.y ) ){\n            pan.y = ease( startPan.y, endPan.y, percent, easing );\n          }\n\n          self.trigger('pan');\n        }\n\n        var startZoom = ani_p.startZoom;\n        var endZoom = ani_p.zoom;\n        var animatingZoom = endZoom != null && isCore;\n        if( animatingZoom ){\n          if( valid( startZoom, endZoom ) ){\n            _p.zoom = ease( startZoom, endZoom, percent, easing );\n          }\n\n          self.trigger('zoom');\n        }\n\n        if( animatingPan || animatingZoom ){\n          self.trigger('viewport');\n        }\n\n        var props = ani_p.style;\n        if( props && isEles ){\n\n          for( var i = 0; i < props.length; i++ ){\n            var prop = props[i];\n            var name = prop.name;\n            var end = prop;\n\n            var start = ani_p.startStyle[ name ];\n            var easedVal = ease( start, end, percent, easing );\n\n            style.overrideBypass( self, name, easedVal );\n          } // for props\n\n        } // if\n\n      }\n\n      if( is.fn(ani_p.step) ){\n        ani_p.step.apply( self, [ now ] );\n      }\n\n      ani_p.progress = percent;\n\n      return percent;\n    }\n\n    function valid(start, end){\n      if( start == null || end == null ){\n        return false;\n      }\n\n      if( is.number(start) && is.number(end) ){\n        return true;\n      } else if( (start) && (end) ){\n        return true;\n      }\n\n      return false;\n    }\n\n    // assumes p0 = 0, p3 = 1\n    function evalCubicBezier( p1, p2, t ){\n      var one_t = 1 - t;\n      var tsq = t*t;\n\n      return ( 3 * one_t * one_t * t * p1 ) + ( 3 * one_t * tsq * p2 ) + tsq * t;\n    }\n\n    function cubicBezier( p1, p2 ){\n      return function( start, end, percent ){\n        return start + (end - start) * evalCubicBezier( p1, p2, percent );\n      };\n    }\n\n    /* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */\n    /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass\n       then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */\n    var generateSpringRK4 = (function () {\n        function springAccelerationForState (state) {\n            return (-state.tension * state.x) - (state.friction * state.v);\n        }\n\n        function springEvaluateStateWithDerivative (initialState, dt, derivative) {\n            var state = {\n                x: initialState.x + derivative.dx * dt,\n                v: initialState.v + derivative.dv * dt,\n                tension: initialState.tension,\n                friction: initialState.friction\n            };\n\n            return { dx: state.v, dv: springAccelerationForState(state) };\n        }\n\n        function springIntegrateState (state, dt) {\n            var a = {\n                    dx: state.v,\n                    dv: springAccelerationForState(state)\n                },\n                b = springEvaluateStateWithDerivative(state, dt * 0.5, a),\n                c = springEvaluateStateWithDerivative(state, dt * 0.5, b),\n                d = springEvaluateStateWithDerivative(state, dt, c),\n                dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),\n                dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);\n\n            state.x = state.x + dxdt * dt;\n            state.v = state.v + dvdt * dt;\n\n            return state;\n        }\n\n        return function springRK4Factory (tension, friction, duration) {\n\n            var initState = {\n                    x: -1,\n                    v: 0,\n                    tension: null,\n                    friction: null\n                },\n                path = [0],\n                time_lapsed = 0,\n                tolerance = 1 / 10000,\n                DT = 16 / 1000,\n                have_duration, dt, last_state;\n\n            tension = parseFloat(tension) || 500;\n            friction = parseFloat(friction) || 20;\n            duration = duration || null;\n\n            initState.tension = tension;\n            initState.friction = friction;\n\n            have_duration = duration !== null;\n\n            /* Calculate the actual time it takes for this animation to complete with the provided conditions. */\n            if (have_duration) {\n                /* Run the simulation without a duration. */\n                time_lapsed = springRK4Factory(tension, friction);\n                /* Compute the adjusted time delta. */\n                dt = time_lapsed / duration * DT;\n            } else {\n                dt = DT;\n            }\n\n            while (true) {\n                /* Next/step function .*/\n                last_state = springIntegrateState(last_state || initState, dt);\n                /* Store the position. */\n                path.push(1 + last_state.x);\n                time_lapsed += 16;\n                /* If the change threshold is reached, break. */\n                if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {\n                    break;\n                }\n            }\n\n            /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the\n               computed path and returns a snapshot of the position according to a given percentComplete. */\n            return !have_duration ? time_lapsed : function(percentComplete) { return path[ (percentComplete * (path.length - 1)) | 0 ]; };\n        };\n    }());\n\n    var easings = {\n      'linear': function( start, end, percent ){\n        return start + (end - start) * percent;\n      },\n\n      // default easings\n      'ease': cubicBezier( 0.25, 0.1, 0.25, 1 ),\n      'ease-in': cubicBezier( 0.42, 0, 1, 1 ),\n      'ease-out': cubicBezier( 0, 0, 0.58, 1 ),\n      'ease-in-out': cubicBezier( 0.42, 0, 0.58, 1 ),\n\n      // sine\n      'ease-in-sine': cubicBezier( 0.47, 0, 0.745, 0.715 ),\n      'ease-out-sine': cubicBezier( 0.39, 0.575, 0.565, 1 ),\n      'ease-in-out-sine': cubicBezier( 0.445, 0.05, 0.55, 0.95 ),\n\n      // quad\n      'ease-in-quad': cubicBezier( 0.55, 0.085, 0.68, 0.53 ),\n      'ease-out-quad': cubicBezier( 0.25, 0.46, 0.45, 0.94 ),\n      'ease-in-out-quad': cubicBezier( 0.455, 0.03, 0.515, 0.955 ),\n\n      // cubic\n      'ease-in-cubic': cubicBezier( 0.55, 0.055, 0.675, 0.19 ),\n      'ease-out-cubic': cubicBezier( 0.215, 0.61, 0.355, 1 ),\n      'ease-in-out-cubic': cubicBezier( 0.645, 0.045, 0.355, 1 ),\n\n      // quart\n      'ease-in-quart': cubicBezier( 0.895, 0.03, 0.685, 0.22 ),\n      'ease-out-quart': cubicBezier( 0.165, 0.84, 0.44, 1 ),\n      'ease-in-out-quart': cubicBezier( 0.77, 0, 0.175, 1 ),\n\n      // quint\n      'ease-in-quint': cubicBezier( 0.755, 0.05, 0.855, 0.06 ),\n      'ease-out-quint': cubicBezier( 0.23, 1, 0.32, 1 ),\n      'ease-in-out-quint': cubicBezier( 0.86, 0, 0.07, 1 ),\n\n      // expo\n      'ease-in-expo': cubicBezier( 0.95, 0.05, 0.795, 0.035 ),\n      'ease-out-expo': cubicBezier( 0.19, 1, 0.22, 1 ),\n      'ease-in-out-expo': cubicBezier( 1, 0, 0, 1 ),\n\n      // circ\n      'ease-in-circ': cubicBezier( 0.6, 0.04, 0.98, 0.335 ),\n      'ease-out-circ': cubicBezier( 0.075, 0.82, 0.165, 1 ),\n      'ease-in-out-circ': cubicBezier( 0.785, 0.135, 0.15, 0.86 ),\n\n\n      // user param easings...\n\n      'spring': function( tension, friction, duration ){\n        var spring = generateSpringRK4( tension, friction, duration );\n\n        return function( start, end, percent ){\n          return start + (end - start) * spring( percent );\n        };\n      },\n\n      'cubic-bezier': function( x1, y1, x2, y2 ){\n        return cubicBezier( x1, y1, x2, y2 );\n      }\n    };\n\n    function ease( startProp, endProp, percent, easingFn ){\n      if( percent < 0 ){\n        percent = 0;\n      } else if( percent > 1 ){\n        percent = 1;\n      }\n\n      var start, end;\n\n      if( startProp.pfValue != null || startProp.value != null ){\n        start = startProp.pfValue != null ? startProp.pfValue : startProp.value;\n      } else {\n        start = startProp;\n      }\n\n      if( endProp.pfValue != null || endProp.value != null ){\n        end = endProp.pfValue != null ? endProp.pfValue : endProp.value;\n      } else {\n        end = endProp;\n      }\n\n      if( is.number(start) && is.number(end) ){\n        return easingFn( start, end, percent );\n\n      } else if( is.array(start) && is.array(end) ){\n        var easedArr = [];\n\n        for( var i = 0; i < end.length; i++ ){\n          var si = start[i];\n          var ei = end[i];\n\n          if( si != null && ei != null ){\n            var val = easingFn(si, ei, percent);\n\n            if( startProp.roundValue ){ val = Math.round( val ); }\n\n            easedArr.push( val );\n          } else {\n            easedArr.push( ei );\n          }\n        }\n\n        return easedArr;\n      }\n\n      return undefined;\n    }\n\n  }\n\n});\n\nmodule.exports = corefn;\n","'use strict';\n\nvar define = require('../define');\n\nvar corefn = ({\n  on: define.on(), // .on( events [, selector] [, data], handler)\n  one: define.on({ unbindSelfOnTrigger: true }),\n  once: define.on({ unbindAllBindersOnTrigger: true }),\n  off: define.off(), // .off( events [, selector] [, handler] )\n  trigger: define.trigger() // .trigger( events [, extraParams] )\n});\n\ndefine.eventAliasesOn( corefn );\n\nmodule.exports = corefn;\n","'use strict';\n\nvar corefn = ({\n\n  png: function( options ){\n    var renderer = this._private.renderer;\n    options = options || {};\n\n    return renderer.png( options );\n  },\n\n  jpg: function( options ){\n    var renderer = this._private.renderer;\n    options = options || {};\n\n    options.bg = options.bg || '#fff';\n\n    return renderer.jpg( options );\n  }\n\n});\n\ncorefn.jpeg = corefn.jpg;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar window = require('../window');\nvar util = require('../util');\nvar Collection = require('../collection');\nvar is = require('../is');\nvar Promise = require('../promise');\nvar define = require('../define');\n\nvar Core = function( opts ){\n  if( !(this instanceof Core) ){\n    return new Core(opts);\n  }\n  var cy = this;\n\n  opts = util.extend({}, opts);\n\n  var container = opts.container;\n\n  // allow for passing a wrapped jquery object\n  // e.g. cytoscape({ container: $('#cy') })\n  if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){\n    container = container[0];\n  }\n\n  var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery\n  reg = reg || {};\n\n  if( reg && reg.cy ){\n    reg.cy.destroy();\n\n    reg = {}; // old instance => replace reg completely\n  }\n\n  var readies = reg.readies = reg.readies || [];\n\n  if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy\n  reg.cy = cy;\n\n  var head = window !== undefined && container !== undefined && !opts.headless;\n  var options = opts;\n  options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout );\n  options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer );\n\n  var defVal = function( def, val, altVal ){\n    if( val !== undefined ){\n      return val;\n    } else if( altVal !== undefined ){\n      return altVal;\n    } else {\n      return def;\n    }\n  };\n\n  var _p = this._private = {\n    container: container, // html dom ele container\n    ready: false, // whether ready has been triggered\n    initrender: false, // has initrender has been triggered\n    options: options, // cached options\n    elements: [], // array of elements\n    id2index: {}, // element id => index in elements array\n    listeners: [], // list of listeners\n    onRenders: [], // rendering listeners\n    aniEles: Collection(this), // elements being animated\n    scratch: {}, // scratch object for core\n    layout: null,\n    renderer: null,\n    notificationsEnabled: true, // whether notifications are sent to the renderer\n    minZoom: 1e-50,\n    maxZoom: 1e50,\n    zoomingEnabled: defVal(true, options.zoomingEnabled),\n    userZoomingEnabled: defVal(true, options.userZoomingEnabled),\n    panningEnabled: defVal(true, options.panningEnabled),\n    userPanningEnabled: defVal(true, options.userPanningEnabled),\n    boxSelectionEnabled: defVal(true, options.boxSelectionEnabled),\n    autolock: defVal(false, options.autolock, options.autolockNodes),\n    autoungrabify: defVal(false, options.autoungrabify, options.autoungrabifyNodes),\n    autounselectify: defVal(false, options.autounselectify),\n    styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,\n    zoom: is.number(options.zoom) ? options.zoom : 1,\n    pan: {\n      x: is.plainObject(options.pan) && is.number(options.pan.x) ? options.pan.x : 0,\n      y: is.plainObject(options.pan) && is.number(options.pan.y) ? options.pan.y : 0\n    },\n    animation: { // object for currently-running animations\n      current: [],\n      queue: []\n    },\n    hasCompoundNodes: false,\n    deferredExecQueue: []\n  };\n\n  // set selection type\n  var selType = options.selectionType;\n  if( selType === undefined || (selType !== 'additive' && selType !== 'single') ){\n    // then set default\n\n    _p.selectionType = 'single';\n  } else {\n    _p.selectionType = selType;\n  }\n\n  // init zoom bounds\n  if( is.number(options.minZoom) && is.number(options.maxZoom) && options.minZoom < options.maxZoom ){\n    _p.minZoom = options.minZoom;\n    _p.maxZoom = options.maxZoom;\n  } else if( is.number(options.minZoom) && options.maxZoom === undefined ){\n    _p.minZoom = options.minZoom;\n  } else if( is.number(options.maxZoom) && options.minZoom === undefined ){\n    _p.maxZoom = options.maxZoom;\n  }\n\n  var loadExtData = function( next ){\n    var anyIsPromise = false;\n\n    for( var i = 0; i < extData.length; i++ ){\n      var datum = extData[i];\n\n      if( is.promise(datum) ){\n        anyIsPromise = true;\n        break;\n      }\n    }\n\n    if( anyIsPromise ){\n      return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init\n    } else {\n      next( extData ); // exec synchronously for convenience\n    }\n  };\n\n  // create the renderer\n  cy.initRenderer( util.extend({\n    hideEdgesOnViewport: options.hideEdgesOnViewport,\n    hideLabelsOnViewport: options.hideLabelsOnViewport,\n    textureOnViewport: options.textureOnViewport,\n    wheelSensitivity: is.number(options.wheelSensitivity) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1,\n    motionBlur: options.motionBlur === undefined ? true : options.motionBlur, // on by default\n    motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity,\n    pixelRatio: is.number(options.pixelRatio) && options.pixelRatio > 0 ? options.pixelRatio : undefined,\n    desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold,\n    touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold\n  }, options.renderer) );\n\n  var extData = [ options.style, options.elements ];\n  loadExtData(function( thens ){\n    var initStyle = thens[0];\n    var initEles = thens[1];\n\n    // init style\n    if( _p.styleEnabled ){\n      cy.setStyle( initStyle );\n    }\n\n    // trigger the passed function for the `initrender` event\n    if( options.initrender ){\n      cy.on('initrender', options.initrender);\n      cy.on('initrender', function(){\n        _p.initrender = true;\n      });\n    }\n\n    // initial load\n    cy.load(initEles, function(){ // onready\n      cy.startAnimationLoop();\n      _p.ready = true;\n\n      // if a ready callback is specified as an option, the bind it\n      if( is.fn( options.ready ) ){\n        cy.on('ready', options.ready);\n      }\n\n      // bind all the ready handlers registered before creating this instance\n      for( var i = 0; i < readies.length; i++ ){\n        var fn = readies[i];\n        cy.on('ready', fn);\n      }\n      if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc\n\n      cy.trigger('ready');\n    }, options.done);\n\n  });\n};\n\nvar corefn = Core.prototype; // short alias\n\nutil.extend(corefn, {\n  instanceString: function(){\n    return 'core';\n  },\n\n  isReady: function(){\n    return this._private.ready;\n  },\n\n  ready: function( fn ){\n    if( this.isReady() ){\n      this.trigger('ready', [], fn); // just calls fn as though triggered via ready event\n    } else {\n      this.on('ready', fn);\n    }\n\n    return this;\n  },\n\n  initrender: function(){\n    return this._private.initrender;\n  },\n\n  destroy: function(){\n    var cy = this;\n\n    cy.stopAnimationLoop();\n\n    cy.notify({ type: 'destroy' }); // destroy the renderer\n\n    var domEle = cy.container();\n    if( domEle ){\n      domEle._cyreg = null;\n\n      while( domEle.childNodes.length > 0 ){\n        domEle.removeChild( domEle.childNodes[0] );\n      }\n    }\n\n    return cy;\n  },\n\n  getElementById: function( id ){\n    var index = this._private.id2index[ id ];\n    if( index !== undefined ){\n      return this._private.elements[ index ];\n    }\n\n    // worst case, return an empty collection\n    return Collection( this );\n  },\n\n  selectionType: function(){\n    return this._private.selectionType;\n  },\n\n  hasCompoundNodes: function(){\n    return this._private.hasCompoundNodes;\n  },\n\n  styleEnabled: function(){\n    return this._private.styleEnabled;\n  },\n\n  addToPool: function( eles ){\n    var elements = this._private.elements;\n    var id2index = this._private.id2index;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n\n      var id = ele._private.data.id;\n      var index = id2index[ id ];\n      var alreadyInPool = index !== undefined;\n\n      if( !alreadyInPool ){\n        index = elements.length;\n        elements.push( ele );\n        id2index[ id ] = index;\n        ele._private.index = index;\n      }\n    }\n\n    return this; // chaining\n  },\n\n  removeFromPool: function( eles ){\n    var elements = this._private.elements;\n    var id2index = this._private.id2index;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n\n      var id = ele._private.data.id;\n      var index = id2index[ id ];\n      var inPool = index !== undefined;\n\n      if( inPool ){\n        this._private.id2index[ id ] = undefined;\n        elements.splice(index, 1);\n\n        // adjust the index of all elements past this index\n        for( var j = index; j < elements.length; j++ ){\n          var jid = elements[j]._private.data.id;\n          id2index[ jid ]--;\n          elements[j]._private.index--;\n        }\n      }\n    }\n  },\n\n  container: function(){\n    return this._private.container;\n  },\n\n  options: function(){\n    return util.copy( this._private.options );\n  },\n\n  json: function( obj ){\n    var cy = this;\n    var _p = cy._private;\n\n    if( is.plainObject(obj) ){ // set\n\n      cy.startBatch();\n\n      if( obj.elements ){\n        var idInJson = {};\n\n        var updateEles = function( jsons, gr ){\n          for( var i = 0; i < jsons.length; i++ ){\n            var json = jsons[i];\n            var id = json.data.id;\n            var ele = cy.getElementById( id );\n\n            idInJson[ id ] = true;\n\n            if( ele.length !== 0 ){ // existing element should be updated\n              ele.json( json );\n            } else { // otherwise should be added\n              if( gr ){\n                cy.add( util.extend({ group: gr }, json) );\n              } else {\n                cy.add( json );\n              }\n            }\n          }\n        };\n\n        if( is.array(obj.elements) ){ // elements: []\n          updateEles( obj.elements );\n\n        } else { // elements: { nodes: [], edges: [] }\n          var grs = ['nodes', 'edges'];\n          for( var i = 0; i < grs.length; i++ ){\n            var gr = grs[i];\n            var elements = obj.elements[ gr ];\n\n            if( is.array(elements) ){\n              updateEles( elements, gr );\n            }\n          }\n        }\n\n        // elements not specified in json should be removed\n        cy.elements().stdFilter(function( ele ){\n          return !idInJson[ ele.id() ];\n        }).remove();\n      }\n\n      if( obj.style ){\n        cy.style( obj.style );\n      }\n\n      if( obj.zoom != null && obj.zoom !== _p.zoom ){\n        cy.zoom( obj.zoom );\n      }\n\n      if( obj.pan ){\n        if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){\n          cy.pan( obj.pan );\n        }\n      }\n\n      var fields = [\n        'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled',\n        'panningEnabled', 'userPanningEnabled',\n        'boxSelectionEnabled',\n        'autolock', 'autoungrabify', 'autounselectify'\n      ];\n\n      for( var i = 0; i < fields.length; i++ ){\n        var f = fields[i];\n\n        if( obj[f] != null ){\n          cy[f]( obj[f] );\n        }\n      }\n\n      cy.endBatch();\n\n      return this; // chaining\n    } else if( obj === undefined ){ // get\n      var json = {};\n\n      json.elements = {};\n      cy.elements().each(function(i, ele){\n        var group = ele.group();\n\n        if( !json.elements[group] ){\n          json.elements[group] = [];\n        }\n\n        json.elements[group].push( ele.json() );\n      });\n\n      if( this._private.styleEnabled ){\n        json.style = cy.style().json();\n      }\n\n      json.zoomingEnabled = cy._private.zoomingEnabled;\n      json.userZoomingEnabled = cy._private.userZoomingEnabled;\n      json.zoom = cy._private.zoom;\n      json.minZoom = cy._private.minZoom;\n      json.maxZoom = cy._private.maxZoom;\n      json.panningEnabled = cy._private.panningEnabled;\n      json.userPanningEnabled = cy._private.userPanningEnabled;\n      json.pan = util.copy( cy._private.pan );\n      json.boxSelectionEnabled = cy._private.boxSelectionEnabled;\n      json.renderer = util.copy( cy._private.options.renderer );\n      json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport;\n      json.hideLabelsOnViewport = cy._private.options.hideLabelsOnViewport;\n      json.textureOnViewport = cy._private.options.textureOnViewport;\n      json.wheelSensitivity = cy._private.options.wheelSensitivity;\n      json.motionBlur = cy._private.options.motionBlur;\n\n      return json;\n    }\n  },\n\n  scratch: define.data({\n    field: 'scratch',\n    bindingEvent: 'scratch',\n    allowBinding: true,\n    allowSetting: true,\n    settingEvent: 'scratch',\n    settingTriggersEvent: true,\n    triggerFnName: 'trigger',\n    allowGetting: true\n  }),\n\n  removeScratch: define.removeData({\n    field: 'scratch',\n    event: 'scratch',\n    triggerFnName: 'trigger',\n    triggerEvent: true\n  })\n\n});\n\n[\n  require('./add-remove'),\n  require('./animation'),\n  require('./events'),\n  require('./export'),\n  require('./layout'),\n  require('./notification'),\n  require('./renderer'),\n  require('./search'),\n  require('./style'),\n  require('./viewport')\n].forEach(function( props ){\n  util.extend( corefn, props );\n});\n\nmodule.exports = Core;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar corefn = ({\n\n  layout: function( params ){\n    var layout = this._private.prevLayout = ( params == null ? this._private.prevLayout : this.makeLayout( params ) );\n\n    layout.run();\n\n    return this; // chaining\n  },\n\n  makeLayout: function( options ){\n    var cy = this;\n\n    if( options == null ){\n      util.error('Layout options must be specified to make a layout');\n      return;\n    }\n\n    if( options.name == null ){\n      util.error('A `name` must be specified to make a layout');\n      return;\n    }\n\n    var name = options.name;\n    var Layout = cy.extension('layout', name);\n\n    if( Layout == null ){\n      util.error('Can not apply layout: No such layout `' + name + '` found; did you include its JS file?');\n      return;\n    }\n\n    var eles;\n    if( is.string( options.eles ) ){\n      eles = cy.$( options.eles );\n    } else {\n      eles = options.eles != null ? options.eles : cy.$();\n    }\n\n    var layout = new Layout( util.extend({}, options, {\n      cy: cy,\n      eles: eles\n    }) );\n\n    return layout;\n  }\n\n});\n\ncorefn.createLayout = corefn.makeLayout;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar corefn = ({\n  notify: function( params ){\n    var _p = this._private;\n\n    if( _p.batchingNotify ){\n      var bEles = _p.batchNotifyEles;\n      var bTypes = _p.batchNotifyTypes;\n\n      if( params.collection ){\n        bEles.merge( params.collection );\n      }\n\n      if( !bTypes.ids[ params.type ] ){\n        bTypes.push( params.type );\n      }\n\n      return; // notifications are disabled during batching\n    }\n\n    if( !_p.notificationsEnabled ){ return; } // exit on disabled\n\n    var renderer = this.renderer();\n\n    renderer.notify(params);\n  },\n\n  notifications: function( bool ){\n    var p = this._private;\n\n    if( bool === undefined ){\n      return p.notificationsEnabled;\n    } else {\n      p.notificationsEnabled = bool ? true : false;\n    }\n  },\n\n  noNotifications: function( callback ){\n    this.notifications(false);\n    callback();\n    this.notifications(true);\n  },\n\n  startBatch: function(){\n    var _p = this._private;\n\n    if( _p.batchCount == null ){\n      _p.batchCount = 0;\n    }\n\n    if( _p.batchCount === 0 ){\n      _p.batchingStyle = _p.batchingNotify = true;\n      _p.batchStyleEles = this.collection();\n      _p.batchNotifyEles = this.collection();\n      _p.batchNotifyTypes = [];\n\n      _p.batchNotifyTypes.ids = {};\n    }\n\n    _p.batchCount++;\n\n    return this;\n  },\n\n  endBatch: function(){\n    var _p = this._private;\n\n    _p.batchCount--;\n\n    if( _p.batchCount === 0 ){\n      // update style for dirty eles\n      _p.batchingStyle = false;\n      _p.batchStyleEles.updateStyle();\n\n      // notify the renderer of queued eles and event types\n      _p.batchingNotify = false;\n      this.notify({\n        type: _p.batchNotifyTypes,\n        collection: _p.batchNotifyEles\n      });\n    }\n\n    return this;\n  },\n\n  batch: function( callback ){\n    this.startBatch();\n    callback();\n    this.endBatch();\n\n    return this;\n  },\n\n  // for backwards compatibility\n  batchData: function( map ){\n    var cy = this;\n\n    return this.batch(function(){\n      for( var id in map ){\n        var data = map[id];\n        var ele = cy.getElementById( id );\n\n        ele.data( data );\n      }\n    });\n  }\n});\n\nmodule.exports = corefn;\n","'use strict';\n\nvar util = require('../util');\n\nvar corefn = ({\n\n  renderTo: function( context, zoom, pan, pxRatio ){\n    var r = this._private.renderer;\n\n    r.renderTo( context, zoom, pan, pxRatio );\n    return this;\n  },\n\n  renderer: function(){\n    return this._private.renderer;\n  },\n\n  forceRender: function(){\n    this.notify({\n      type: 'draw'\n    });\n\n    return this;\n  },\n\n  resize: function(){\n    this.notify({\n      type: 'resize'\n    });\n\n    this.trigger('resize');\n\n    return this;\n  },\n\n  initRenderer: function( options ){\n    var cy = this;\n\n    var RendererProto = cy.extension('renderer', options.name);\n    if( RendererProto == null ){\n      util.error('Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name);\n      return;\n    }\n\n    var rOpts = util.extend({}, options, {\n      cy: cy\n    });\n    var renderer = cy._private.renderer = new RendererProto( rOpts );\n\n    renderer.init( rOpts );\n\n  },\n\n  triggerOnRender: function(){\n    var cbs = this._private.onRenders;\n\n    for( var i = 0; i < cbs.length; i++ ){\n      var cb = cbs[i];\n\n      cb();\n    }\n\n    return this;\n  },\n\n  onRender: function( cb ){\n    this._private.onRenders.push( cb );\n\n    return this;\n  },\n\n  offRender: function( fn ){\n    var cbs = this._private.onRenders;\n\n    if( fn == null ){ // unbind all\n      this._private.onRenders = [];\n      return this;\n    }\n\n    for( var i = 0; i < cbs.length; i++ ){ // unbind specified\n      var cb = cbs[i];\n\n      if( fn === cb ){\n        cbs.splice( i, 1 );\n        break;\n      }\n    }\n\n    return this;\n  }\n\n});\n\ncorefn.invalidateDimensions = corefn.resize;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar is = require('../is');\nvar Collection = require('../collection');\n\nvar corefn = ({\n\n  // get a collection\n  // - empty collection on no args\n  // - collection of elements in the graph on selector arg\n  // - guarantee a returned collection when elements or collection specified\n  collection: function( eles, opts ){\n\n    if( is.string( eles ) ){\n      return this.$( eles );\n\n    } else if( is.elementOrCollection( eles ) ){\n      return eles.collection();\n\n    } else if( is.array( eles ) ){\n      return Collection( this, eles, opts );\n    }\n\n    return Collection( this );\n  },\n\n  nodes: function( selector ){\n    var nodes = this.$(function(){\n      return this.isNode();\n    });\n\n    if( selector ){\n      return nodes.filter( selector );\n    }\n\n    return nodes;\n  },\n\n  edges: function( selector ){\n    var edges = this.$(function(){\n      return this.isEdge();\n    });\n\n    if( selector ){\n      return edges.filter( selector );\n    }\n\n    return edges;\n  },\n\n  // search the graph like jQuery\n  $: function( selector ){\n    var eles = new Collection( this, this._private.elements );\n\n    if( selector ){\n      return eles.filter( selector );\n    }\n\n    return eles;\n  }\n\n});\n\n// aliases\ncorefn.elements = corefn.filter = corefn.$;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar is = require('../is');\nvar Style = require('../style');\n\nvar corefn = ({\n\n  style: function( newStyle ){\n    if( newStyle ){\n      var s = this.setStyle( newStyle );\n\n      s.update();\n    }\n\n    return this._private.style;\n  },\n\n  setStyle: function( style ){\n    var _p = this._private;\n\n    if( is.stylesheet(style) ){\n      _p.style = style.generateStyle(this);\n\n    } else if( is.array(style) ) {\n      _p.style = Style.fromJson(this, style);\n\n    } else if( is.string(style) ){\n      _p.style = Style.fromString(this, style);\n\n    } else {\n      _p.style = Style( this );\n    }\n\n    return _p.style;\n  }\n});\n\nmodule.exports = corefn;\n","'use strict';\n\nvar is = require('../is');\n\nvar corefn = ({\n\n  autolock: function(bool){\n    if( bool !== undefined ){\n      this._private.autolock = bool ? true : false;\n    } else {\n      return this._private.autolock;\n    }\n\n    return this; // chaining\n  },\n\n  autoungrabify: function(bool){\n    if( bool !== undefined ){\n      this._private.autoungrabify = bool ? true : false;\n    } else {\n      return this._private.autoungrabify;\n    }\n\n    return this; // chaining\n  },\n\n  autounselectify: function(bool){\n    if( bool !== undefined ){\n      this._private.autounselectify = bool ? true : false;\n    } else {\n      return this._private.autounselectify;\n    }\n\n    return this; // chaining\n  },\n\n  panningEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.panningEnabled = bool ? true : false;\n    } else {\n      return this._private.panningEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  userPanningEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.userPanningEnabled = bool ? true : false;\n    } else {\n      return this._private.userPanningEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  zoomingEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.zoomingEnabled = bool ? true : false;\n    } else {\n      return this._private.zoomingEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  userZoomingEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.userZoomingEnabled = bool ? true : false;\n    } else {\n      return this._private.userZoomingEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  boxSelectionEnabled: function( bool ){\n    if( bool !== undefined ){\n      this._private.boxSelectionEnabled = bool ? true : false;\n    } else {\n      return this._private.boxSelectionEnabled;\n    }\n\n    return this; // chaining\n  },\n\n  pan: function(){\n    var args = arguments;\n    var pan = this._private.pan;\n    var dim, val, dims, x, y;\n\n    switch( args.length ){\n    case 0: // .pan()\n      return pan;\n\n    case 1:\n\n      if( is.string( args[0] ) ){ // .pan('x')\n        dim = args[0];\n        return pan[ dim ];\n\n      } else if( is.plainObject( args[0] ) ) { // .pan({ x: 0, y: 100 })\n        if( !this._private.panningEnabled ){\n          return this;\n        }\n\n        dims = args[0];\n        x = dims.x;\n        y = dims.y;\n\n        if( is.number(x) ){\n          pan.x = x;\n        }\n\n        if( is.number(y) ){\n          pan.y = y;\n        }\n\n        this.trigger('pan viewport');\n      }\n      break;\n\n    case 2: // .pan('x', 100)\n      if( !this._private.panningEnabled ){\n        return this;\n      }\n\n      dim = args[0];\n      val = args[1];\n\n      if( (dim === 'x' || dim === 'y') && is.number(val) ){\n        pan[dim] = val;\n      }\n\n      this.trigger('pan viewport');\n      break;\n\n    default:\n      break; // invalid\n    }\n\n    this.notify({ // notify the renderer that the viewport changed\n      type: 'viewport'\n    });\n\n    return this; // chaining\n  },\n\n  panBy: function(params){\n    var args = arguments;\n    var pan = this._private.pan;\n    var dim, val, dims, x, y;\n\n    if( !this._private.panningEnabled ){\n      return this;\n    }\n\n    switch( args.length ){\n    case 1:\n\n      if( is.plainObject( args[0] ) ) { // .panBy({ x: 0, y: 100 })\n        dims = args[0];\n        x = dims.x;\n        y = dims.y;\n\n        if( is.number(x) ){\n          pan.x += x;\n        }\n\n        if( is.number(y) ){\n          pan.y += y;\n        }\n\n        this.trigger('pan viewport');\n      }\n      break;\n\n    case 2: // .panBy('x', 100)\n      dim = args[0];\n      val = args[1];\n\n      if( (dim === 'x' || dim === 'y') && is.number(val) ){\n        pan[dim] += val;\n      }\n\n      this.trigger('pan viewport');\n      break;\n\n    default:\n      break; // invalid\n    }\n\n    this.notify({ // notify the renderer that the viewport changed\n      type: 'viewport'\n    });\n\n    return this; // chaining\n  },\n\n  fit: function( elements, padding ){\n    var viewportState = this.getFitViewport( elements, padding );\n\n    if( viewportState ){\n      var _p = this._private;\n      _p.zoom = viewportState.zoom;\n      _p.pan = viewportState.pan;\n\n      this.trigger('pan zoom viewport');\n\n      this.notify({ // notify the renderer that the viewport changed\n        type: 'viewport'\n      });\n    }\n\n    return this; // chaining\n  },\n\n  getFitViewport: function( elements, padding ){\n    if( is.number(elements) && padding === undefined ){ // elements is optional\n      padding = elements;\n      elements = undefined;\n    }\n\n    if( !this._private.panningEnabled || !this._private.zoomingEnabled ){\n      return;\n    }\n\n    var bb;\n\n    if( is.string(elements) ){\n      var sel = elements;\n      elements = this.$( sel );\n\n    } else if( is.boundingBox(elements) ){ // assume bb\n      var bbe = elements;\n      bb = {\n        x1: bbe.x1,\n        y1: bbe.y1,\n        x2: bbe.x2,\n        y2: bbe.y2\n      };\n\n      bb.w = bb.x2 - bb.x1;\n      bb.h = bb.y2 - bb.y1;\n\n    } else if( !is.elementOrCollection(elements) ){\n      elements = this.elements();\n    }\n\n    bb = bb || elements.boundingBox();\n\n    var w = this.width();\n    var h = this.height();\n    var zoom;\n    padding = is.number(padding) ? padding : 0;\n\n    if( !isNaN(w) && !isNaN(h) && w > 0 && h > 0 && !isNaN(bb.w) && !isNaN(bb.h) &&  bb.w > 0 && bb.h > 0 ){\n      zoom = Math.min( (w - 2*padding)/bb.w, (h - 2*padding)/bb.h );\n\n      // crop zoom\n      zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;\n      zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;\n\n      var pan = { // now pan to middle\n        x: (w - zoom*( bb.x1 + bb.x2 ))/2,\n        y: (h - zoom*( bb.y1 + bb.y2 ))/2\n      };\n\n      return {\n        zoom: zoom,\n        pan: pan\n      };\n    }\n\n    return;\n  },\n\n  minZoom: function( zoom ){\n    if( zoom === undefined ){\n      return this._private.minZoom;\n    } else if( is.number(zoom) ){\n      this._private.minZoom = zoom;\n    }\n\n    return this;\n  },\n\n  maxZoom: function( zoom ){\n    if( zoom === undefined ){\n      return this._private.maxZoom;\n    } else if( is.number(zoom) ){\n      this._private.maxZoom = zoom;\n    }\n\n    return this;\n  },\n\n  zoom: function( params ){\n    var pos; // in rendered px\n    var zoom;\n\n    if( params === undefined ){ // then get the zoom\n      return this._private.zoom;\n\n    } else if( is.number(params) ){ // then set the zoom\n      zoom = params;\n\n    } else if( is.plainObject(params) ){ // then zoom about a point\n      zoom = params.level;\n\n      if( params.position ){\n        var p = params.position;\n        var pan = this._private.pan;\n        var z = this._private.zoom;\n\n        pos = { // convert to rendered px\n          x: p.x * z + pan.x,\n          y: p.y * z + pan.y\n        };\n      } else if( params.renderedPosition ){\n        pos = params.renderedPosition;\n      }\n\n      if( pos && !this._private.panningEnabled ){\n        return this; // panning disabled\n      }\n    }\n\n    if( !this._private.zoomingEnabled ){\n      return this; // zooming disabled\n    }\n\n    if( !is.number(zoom) || ( pos && (!is.number(pos.x) || !is.number(pos.y)) ) ){\n      return this; // can't zoom with invalid params\n    }\n\n    // crop zoom\n    zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;\n    zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;\n\n    if( pos ){ // set zoom about position\n      var pan1 = this._private.pan;\n      var zoom1 = this._private.zoom;\n      var zoom2 = zoom;\n\n      var pan2 = {\n        x: -zoom2/zoom1 * (pos.x - pan1.x) + pos.x,\n        y: -zoom2/zoom1 * (pos.y - pan1.y) + pos.y\n      };\n\n      this._private.zoom = zoom;\n      this._private.pan = pan2;\n\n      var posChanged = pan1.x !== pan2.x || pan1.y !== pan2.y;\n      this.trigger(' zoom ' + (posChanged ? ' pan ' : '') + ' viewport ' );\n\n    } else { // just set the zoom\n      this._private.zoom = zoom;\n      this.trigger('zoom viewport');\n    }\n\n    this.notify({ // notify the renderer that the viewport changed\n      type: 'viewport'\n    });\n\n    return this; // chaining\n  },\n\n  viewport: function( opts ){\n    var _p = this._private;\n    var zoomDefd = true;\n    var panDefd = true;\n    var events = []; // to trigger\n    var zoomFailed = false;\n    var panFailed = false;\n\n    if( !opts ){ return this; }\n    if( !is.number(opts.zoom) ){ zoomDefd = false; }\n    if( !is.plainObject(opts.pan) ){ panDefd = false; }\n    if( !zoomDefd && !panDefd ){ return this; }\n\n    if( zoomDefd ){\n      var z = opts.zoom;\n\n      if( z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled ){\n        zoomFailed = true;\n\n      } else {\n        _p.zoom = z;\n\n        events.push('zoom');\n      }\n    }\n\n    if( panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled ){\n      var p = opts.pan;\n\n      if( is.number(p.x) ){\n        _p.pan.x = p.x;\n        panFailed = false;\n      }\n\n      if( is.number(p.y) ){\n        _p.pan.y = p.y;\n        panFailed = false;\n      }\n\n      if( !panFailed ){\n        events.push('pan');\n      }\n    }\n\n    if( events.length > 0 ){\n      events.push('viewport');\n      this.trigger( events.join(' ') );\n\n      this.notify({\n        type: 'viewport'\n      });\n    }\n\n    return this; // chaining\n  },\n\n  center: function( elements ){\n    var pan = this.getCenterPan( elements );\n\n    if( pan ){\n      this._private.pan = pan;\n\n      this.trigger('pan viewport');\n\n      this.notify({ // notify the renderer that the viewport changed\n        type: 'viewport'\n      });\n    }\n\n    return this; // chaining\n  },\n\n  getCenterPan: function( elements, zoom ){\n    if( !this._private.panningEnabled ){\n      return;\n    }\n\n    if( is.string(elements) ){\n      var selector = elements;\n      elements = this.elements( selector );\n    } else if( !is.elementOrCollection(elements) ){\n      elements = this.elements();\n    }\n\n    var bb = elements.boundingBox();\n    var w = this.width();\n    var h = this.height();\n    zoom = zoom === undefined ? this._private.zoom : zoom;\n\n    var pan = { // middle\n      x: (w - zoom*( bb.x1 + bb.x2 ))/2,\n      y: (h - zoom*( bb.y1 + bb.y2 ))/2\n    };\n\n    return pan;\n  },\n\n  reset: function(){\n    if( !this._private.panningEnabled || !this._private.zoomingEnabled ){\n      return this;\n    }\n\n    this.viewport({\n      pan: { x: 0, y: 0 },\n      zoom: 1\n    });\n\n    return this; // chaining\n  },\n\n  width: function(){\n    var container = this._private.container;\n\n    if( container ){\n      return container.clientWidth;\n    }\n\n    return 1; // fallback if no container (not 0 b/c can be used for dividing etc)\n  },\n\n  height: function(){\n    var container = this._private.container;\n\n    if( container ){\n      return container.clientHeight;\n    }\n\n    return 1; // fallback if no container (not 0 b/c can be used for dividing etc)\n  },\n\n  extent: function(){\n    var pan = this._private.pan;\n    var zoom = this._private.zoom;\n    var rb = this.renderedExtent();\n\n    var b = {\n      x1: ( rb.x1 - pan.x )/zoom,\n      x2: ( rb.x2 - pan.x )/zoom,\n      y1: ( rb.y1 - pan.y )/zoom,\n      y2: ( rb.y2 - pan.y )/zoom\n    };\n\n    b.w = b.x2 - b.x1;\n    b.h = b.y2 - b.y1;\n\n    return b;\n  },\n\n  renderedExtent: function(){\n    var width = this.width();\n    var height = this.height();\n\n    return {\n      x1: 0,\n      y1: 0,\n      x2: width,\n      y2: height,\n      w: width,\n      h: height\n    };\n  }\n});\n\n// aliases\ncorefn.centre = corefn.center;\n\n// backwards compatibility\ncorefn.autolockNodes = corefn.autolock;\ncorefn.autoungrabifyNodes = corefn.autoungrabify;\n\nmodule.exports = corefn;\n","'use strict';\n\n// use this module to cherry pick functions into your prototype\n// (useful for functions shared between the core and collections, for example)\n\n// e.g.\n// var foo = define.foo({ /* params... */ })\n\nvar util = require('./util');\nvar is = require('./is');\nvar Selector = require('./selector');\nvar Promise = require('./promise');\nvar Event = require('./event');\nvar Animation = require('./animation');\n\nvar define = {\n\n  // access data field\n  data: function( params ){\n    var defaults = {\n      field: 'data',\n      bindingEvent: 'data',\n      allowBinding: false,\n      allowSetting: false,\n      allowGetting: false,\n      settingEvent: 'data',\n      settingTriggersEvent: false,\n      triggerFnName: 'trigger',\n      immutableKeys: {}, // key => true if immutable\n      updateStyle: false,\n      onSet: function( self ){},\n      canSet: function( self ){ return true; }\n    };\n    params = util.extend({}, defaults, params);\n\n    return function dataImpl( name, value ){\n      var p = params;\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var single = selfIsArrayLike ? self[0] : self;\n\n      // .data('foo', ...)\n      if( is.string(name) ){ // set or get property\n\n        // .data('foo')\n        if( p.allowGetting && value === undefined ){ // get\n\n          var ret;\n          if( single ){\n            ret = single._private[ p.field ][ name ];\n          }\n          return ret;\n\n        // .data('foo', 'bar')\n        } else if( p.allowSetting && value !== undefined ) { // set\n          var valid = !p.immutableKeys[name];\n          if( valid ){\n            for( var i = 0, l = all.length; i < l; i++ ){\n              if( p.canSet( all[i] ) ){\n                all[i]._private[ p.field ][ name ] = value;\n              }\n            }\n\n            // update mappers if asked\n            if( p.updateStyle ){ self.updateStyle(); }\n\n            // call onSet callback\n            p.onSet( self );\n\n            if( p.settingTriggersEvent ){\n              self[ p.triggerFnName ]( p.settingEvent );\n            }\n          }\n        }\n\n      // .data({ 'foo': 'bar' })\n      } else if( p.allowSetting && is.plainObject(name) ){ // extend\n        var obj = name;\n        var k, v;\n\n        for( k in obj ){\n          v = obj[ k ];\n\n          var valid = !p.immutableKeys[k];\n          if( valid ){\n            for( var i = 0, l = all.length; i < l; i++ ){\n              if( p.canSet( all[i] ) ){\n                all[i]._private[ p.field ][ k ] = v;\n              }\n            }\n          }\n        }\n\n        // update mappers if asked\n        if( p.updateStyle ){ self.updateStyle(); }\n\n        // call onSet callback\n        p.onSet( self );\n\n        if( p.settingTriggersEvent ){\n          self[ p.triggerFnName ]( p.settingEvent );\n        }\n\n      // .data(function(){ ... })\n      } else if( p.allowBinding && is.fn(name) ){ // bind to event\n        var fn = name;\n        self.bind( p.bindingEvent, fn );\n\n      // .data()\n      } else if( p.allowGetting && name === undefined ){ // get whole object\n        var ret;\n        if( single ){\n          ret = single._private[ p.field ];\n        }\n        return ret;\n      }\n\n      return self; // maintain chainability\n    }; // function\n  }, // data\n\n  // remove data field\n  removeData: function( params ){\n    var defaults = {\n      field: 'data',\n      event: 'data',\n      triggerFnName: 'trigger',\n      triggerEvent: false,\n      immutableKeys: {} // key => true if immutable\n    };\n    params = util.extend({}, defaults, params);\n\n    return function removeDataImpl( names ){\n      var p = params;\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n      // .removeData('foo bar')\n      if( is.string(names) ){ // then get the list of keys, and delete them\n        var keys = names.split(/\\s+/);\n        var l = keys.length;\n\n        for( var i = 0; i < l; i++ ){ // delete each non-empty key\n          var key = keys[i];\n          if( is.emptyString(key) ){ continue; }\n\n          var valid = !p.immutableKeys[ key ]; // not valid if immutable\n          if( valid ){\n            for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){\n              all[ i_a ]._private[ p.field ][ key ] = undefined;\n            }\n          }\n        }\n\n        if( p.triggerEvent ){\n          self[ p.triggerFnName ]( p.event );\n        }\n\n      // .removeData()\n      } else if( names === undefined ){ // then delete all keys\n\n        for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){\n          var _privateFields = all[ i_a ]._private[ p.field ];\n\n          for( var key in _privateFields ){\n            var validKeyToDelete = !p.immutableKeys[ key ];\n\n            if( validKeyToDelete ){\n              _privateFields[ key ] = undefined;\n            }\n          }\n        }\n\n        if( p.triggerEvent ){\n          self[ p.triggerFnName ]( p.event );\n        }\n      }\n\n      return self; // maintain chaining\n    }; // function\n  }, // removeData\n\n  // event function reusable stuff\n  event: {\n    regex: /(\\w+)(\\.\\w+)?/, // regex for matching event strings (e.g. \"click.namespace\")\n    optionalTypeRegex: /(\\w+)?(\\.\\w+)?/,\n    falseCallback: function(){ return false; }\n  },\n\n  // event binding\n  on: function( params ){\n    var defaults = {\n      unbindSelfOnTrigger: false,\n      unbindAllBindersOnTrigger: false\n    };\n    params = util.extend({}, defaults, params);\n\n    return function onImpl(events, selector, data, callback){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var eventsIsString = is.string(events);\n      var p = params;\n\n      if( is.plainObject(selector) ){ // selector is actually data\n        callback = data;\n        data = selector;\n        selector = undefined;\n      } else if( is.fn(selector) || selector === false ){ // selector is actually callback\n        callback = selector;\n        data = undefined;\n        selector = undefined;\n      }\n\n      if( is.fn(data) || data === false ){ // data is actually callback\n        callback = data;\n        data = undefined;\n      }\n\n      // if there isn't a callback, we can't really do anything\n      // (can't speak for mapped events arg version)\n      if( !(is.fn(callback) || callback === false) && eventsIsString ){\n        return self; // maintain chaining\n      }\n\n      if( eventsIsString ){ // then convert to map\n        var map = {};\n        map[ events ] = callback;\n        events = map;\n      }\n\n      for( var evts in events ){\n        callback = events[evts];\n        if( callback === false ){\n          callback = define.event.falseCallback;\n        }\n\n        if( !is.fn(callback) ){ continue; }\n\n        evts = evts.split(/\\s+/);\n        for( var i = 0; i < evts.length; i++ ){\n          var evt = evts[i];\n          if( is.emptyString(evt) ){ continue; }\n\n          var match = evt.match( define.event.regex ); // type[.namespace]\n\n          if( match ){\n            var type = match[1];\n            var namespace = match[2] ? match[2] : undefined;\n\n            var listener = {\n              callback: callback, // callback to run\n              data: data, // extra data in eventObj.data\n              delegated: selector ? true : false, // whether the evt is delegated\n              selector: selector, // the selector to match for delegated events\n              selObj: new Selector(selector), // cached selector object to save rebuilding\n              type: type, // the event type (e.g. 'click')\n              namespace: namespace, // the event namespace (e.g. \".foo\")\n              unbindSelfOnTrigger: p.unbindSelfOnTrigger,\n              unbindAllBindersOnTrigger: p.unbindAllBindersOnTrigger,\n              binders: all // who bound together\n            };\n\n            for( var j = 0; j < all.length; j++ ){\n              var _p = all[j]._private;\n\n              _p.listeners = _p.listeners || [];\n              _p.listeners.push( listener );\n            }\n          }\n        } // for events array\n      } // for events map\n\n      return self; // maintain chaining\n    }; // function\n  }, // on\n\n  eventAliasesOn: function( proto ){\n    var p = proto;\n\n    p.addListener = p.listen = p.bind = p.on;\n    p.removeListener = p.unlisten = p.unbind = p.off;\n    p.emit = p.trigger;\n\n    // this is just a wrapper alias of .on()\n    p.pon = p.promiseOn = function( events, selector ){\n      var self = this;\n      var args = Array.prototype.slice.call( arguments, 0 );\n\n      return new Promise(function( resolve, reject ){\n        var callback = function( e ){\n          self.off.apply( self, offArgs );\n\n          resolve( e );\n        };\n\n        var onArgs = args.concat([ callback ]);\n        var offArgs = onArgs.concat([]);\n\n        self.on.apply( self, onArgs );\n      });\n    };\n  },\n\n  off: function offImpl( params ){\n    var defaults = {\n    };\n    params = util.extend({}, defaults, params);\n\n    return function(events, selector, callback){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var eventsIsString = is.string(events);\n\n      if( arguments.length === 0 ){ // then unbind all\n\n        for( var i = 0; i < all.length; i++ ){\n          all[i]._private.listeners = [];\n        }\n\n        return self; // maintain chaining\n      }\n\n      if( is.fn(selector) || selector === false ){ // selector is actually callback\n        callback = selector;\n        selector = undefined;\n      }\n\n      if( eventsIsString ){ // then convert to map\n        var map = {};\n        map[ events ] = callback;\n        events = map;\n      }\n\n      for( var evts in events ){\n        callback = events[evts];\n\n        if( callback === false ){\n          callback = define.event.falseCallback;\n        }\n\n        evts = evts.split(/\\s+/);\n        for( var h = 0; h < evts.length; h++ ){\n          var evt = evts[h];\n          if( is.emptyString(evt) ){ continue; }\n\n          var match = evt.match( define.event.optionalTypeRegex ); // [type][.namespace]\n          if( match ){\n            var type = match[1] ? match[1] : undefined;\n            var namespace = match[2] ? match[2] : undefined;\n\n            for( var i = 0; i < all.length; i++ ){ //\n              var listeners = all[i]._private.listeners = all[i]._private.listeners || [];\n\n              for( var j = 0; j < listeners.length; j++ ){\n                var listener = listeners[j];\n                var nsMatches = !namespace || namespace === listener.namespace;\n                var typeMatches = !type || listener.type === type;\n                var cbMatches = !callback || callback === listener.callback;\n                var listenerMatches = nsMatches && typeMatches && cbMatches;\n\n                // delete listener if it matches\n                if( listenerMatches ){\n                  listeners.splice(j, 1);\n                  j--;\n                }\n              } // for listeners\n            } // for all\n          } // if match\n        } // for events array\n\n      } // for events map\n\n      return self; // maintain chaining\n    }; // function\n  }, // off\n\n  trigger: function( params ){\n    var defaults = {};\n    params = util.extend({}, defaults, params);\n\n    return function triggerImpl(events, extraParams, fnToTrigger){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var eventsIsString = is.string(events);\n      var eventsIsObject = is.plainObject(events);\n      var eventsIsEvent = is.event(events);\n      var cy = this._private.cy || ( is.core(this) ? this : null );\n      var hasCompounds = cy ? cy.hasCompoundNodes() : false;\n\n      if( eventsIsString ){ // then make a plain event object for each event name\n        var evts = events.split(/\\s+/);\n        events = [];\n\n        for( var i = 0; i < evts.length; i++ ){\n          var evt = evts[i];\n          if( is.emptyString(evt) ){ continue; }\n\n          var match = evt.match( define.event.regex ); // type[.namespace]\n          var type = match[1];\n          var namespace = match[2] ? match[2] : undefined;\n\n          events.push( {\n            type: type,\n            namespace: namespace\n          } );\n        }\n      } else if( eventsIsObject ){ // put in length 1 array\n        var eventArgObj = events;\n\n        events = [ eventArgObj ];\n      }\n\n      if( extraParams ){\n        if( !is.array(extraParams) ){ // make sure extra params are in an array if specified\n          extraParams = [ extraParams ];\n        }\n      } else { // otherwise, we've got nothing\n        extraParams = [];\n      }\n\n      for( var i = 0; i < events.length; i++ ){ // trigger each event in order\n        var evtObj = events[i];\n\n        for( var j = 0; j < all.length; j++ ){ // for each\n          var triggerer = all[j];\n          var listeners = triggerer._private.listeners = triggerer._private.listeners || [];\n          var triggererIsElement = is.element(triggerer);\n          var bubbleUp = triggererIsElement || params.layout;\n\n          // create the event for this element from the event object\n          var evt;\n\n          if( eventsIsEvent ){ // then just get the object\n            evt = evtObj;\n\n            evt.cyTarget = evt.cyTarget || triggerer;\n            evt.cy = evt.cy || cy;\n\n          } else { // then we have to make one\n            evt = new Event( evtObj, {\n              cyTarget: triggerer,\n              cy: cy,\n              namespace: evtObj.namespace\n            } );\n          }\n\n          // if a layout was specified, then put it in the typed event\n          if( evtObj.layout ){\n            evt.layout = evtObj.layout;\n          }\n\n          // if triggered by layout, put in event\n          if( params.layout ){\n            evt.layout = triggerer;\n          }\n\n          // create a rendered position based on the passed position\n          if( evt.cyPosition ){\n            var pos = evt.cyPosition;\n            var zoom = cy.zoom();\n            var pan = cy.pan();\n\n            evt.cyRenderedPosition = {\n              x: pos.x * zoom + pan.x,\n              y: pos.y * zoom + pan.y\n            };\n          }\n\n          if( fnToTrigger ){ // then override the listeners list with just the one we specified\n            listeners = [{\n              namespace: evt.namespace,\n              type: evt.type,\n              callback: fnToTrigger\n            }];\n          }\n\n          for( var k = 0; k < listeners.length; k++ ){ // check each listener\n            var lis = listeners[k];\n            var nsMatches = !lis.namespace || lis.namespace === evt.namespace;\n            var typeMatches = lis.type === evt.type;\n            var targetMatches = lis.delegated ? ( triggerer !== evt.cyTarget && is.element(evt.cyTarget) && lis.selObj.matches(evt.cyTarget) ) : (true); // we're not going to validate the hierarchy; that's too expensive\n            var listenerMatches = nsMatches && typeMatches && targetMatches;\n\n            if( listenerMatches ){ // then trigger it\n              var args = [ evt ];\n              args = args.concat( extraParams ); // add extra params to args list\n\n              if( lis.data ){ // add on data plugged into binding\n                evt.data = lis.data;\n              } else { // or clear it in case the event obj is reused\n                evt.data = undefined;\n              }\n\n              if( lis.unbindSelfOnTrigger || lis.unbindAllBindersOnTrigger ){ // then remove listener\n                listeners.splice(k, 1);\n                k--;\n              }\n\n              if( lis.unbindAllBindersOnTrigger ){ // then delete the listener for all binders\n                var binders = lis.binders;\n                for( var l = 0; l < binders.length; l++ ){\n                  var binder = binders[l];\n                  if( !binder || binder === triggerer ){ continue; } // already handled triggerer or we can't handle it\n\n                  var binderListeners = binder._private.listeners;\n                  for( var m = 0; m < binderListeners.length; m++ ){\n                    var binderListener = binderListeners[m];\n\n                    if( binderListener === lis ){ // delete listener from list\n                      binderListeners.splice(m, 1);\n                      m--;\n                    }\n                  }\n                }\n              }\n\n              // run the callback\n              var context = lis.delegated ? evt.cyTarget : triggerer;\n              var ret = lis.callback.apply( context, args );\n\n              if( ret === false || evt.isPropagationStopped() ){\n                // then don't bubble\n                bubbleUp = false;\n\n                if( ret === false ){\n                  // returning false is a shorthand for stopping propagation and preventing the def. action\n                  evt.stopPropagation();\n                  evt.preventDefault();\n                }\n              }\n            } // if listener matches\n          } // for each listener\n\n          // bubble up event for elements\n          if( bubbleUp ){\n            var parent = hasCompounds ? triggerer._private.parent : null;\n            var hasParent = parent != null && parent.length !== 0;\n\n            if( hasParent ){ // then bubble up to parent\n              parent = parent[0];\n              parent.trigger(evt);\n            } else { // otherwise, bubble up to the core\n              cy.trigger(evt);\n            }\n          }\n\n        } // for each of all\n      } // for each event\n\n      return self; // maintain chaining\n    }; // function\n  }, // trigger\n\n  animated: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function animatedImpl(){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return false; }\n\n      var ele = all[0];\n\n      if( ele ){\n        return ele._private.animation.current.length > 0;\n      }\n    };\n  }, // animated\n\n  clearQueue: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function clearQueueImpl(){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      for( var i = 0; i < all.length; i++ ){\n        var ele = all[i];\n        ele._private.animation.queue = [];\n      }\n\n      return this;\n    };\n  }, // clearQueue\n\n  delay: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function delayImpl( time, complete ){\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      return this.animate({\n        delay: time,\n        duration: time,\n        complete: complete\n      });\n    };\n  }, // delay\n\n  delayAnimation: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function delayAnimationImpl( time, complete ){\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      return this.animation({\n        delay: time,\n        duration: time,\n        complete: complete\n      });\n    };\n  }, // delay\n\n  animation: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function animationImpl( properties, params ){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n      var isCore = !selfIsArrayLike;\n      var isEles = !isCore;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      var style = cy.style();\n\n      properties = util.extend( {}, properties, params );\n\n      if( properties.duration === undefined ){\n        properties.duration = 400;\n      }\n\n      switch( properties.duration ){\n      case 'slow':\n        properties.duration = 600;\n        break;\n      case 'fast':\n        properties.duration = 200;\n        break;\n      }\n\n      var propertiesEmpty = true;\n      if( properties ){ for( var i in properties ){ // jshint ignore:line\n        propertiesEmpty = false;\n        break;\n      } }\n\n      if( propertiesEmpty ){\n        return new Animation( all[0], properties ); // nothing to animate\n      }\n\n      if( isEles ){\n        properties.style = style.getPropsList( properties.style || properties.css );\n\n        properties.css = undefined;\n      }\n\n      if( properties.renderedPosition && isEles ){\n        var rpos = properties.renderedPosition;\n        var pan = cy.pan();\n        var zoom = cy.zoom();\n\n        properties.position = {\n          x: ( rpos.x - pan.x ) /zoom,\n          y: ( rpos.y - pan.y ) /zoom\n        };\n      }\n\n      // override pan w/ panBy if set\n      if( properties.panBy && isCore ){\n        var panBy = properties.panBy;\n        var cyPan = cy.pan();\n\n        properties.pan = {\n          x: cyPan.x + panBy.x,\n          y: cyPan.y + panBy.y\n        };\n      }\n\n      // override pan w/ center if set\n      var center = properties.center || properties.centre;\n      if( center && isCore ){\n        var centerPan = cy.getCenterPan( center.eles, properties.zoom );\n\n        if( centerPan ){\n          properties.pan = centerPan;\n        }\n      }\n\n      // override pan & zoom w/ fit if set\n      if( properties.fit && isCore ){\n        var fit = properties.fit;\n        var fitVp = cy.getFitViewport( fit.eles || fit.boundingBox, fit.padding );\n\n        if( fitVp ){\n          properties.pan = fitVp.pan;\n          properties.zoom = fitVp.zoom;\n        }\n      }\n\n      return new Animation( all[0], properties );\n    };\n  }, // animate\n\n  animate: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function animateImpl( properties, params ){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      if( params ){\n        properties = util.extend( {}, properties, params );\n      }\n\n      // manually hook and run the animation\n      for( var i = 0; i < all.length; i++ ){\n        var ele = all[i];\n        var queue = ele.animated() && (properties.queue === undefined || properties.queue);\n\n        var ani = ele.animation( properties, (queue ? { queue: true } : undefined) );\n\n        ani.play();\n      }\n\n      return this; // chaining\n    };\n  }, // animate\n\n  stop: function( fnParams ){\n    var defaults = {};\n    fnParams = util.extend({}, defaults, fnParams);\n\n    return function stopImpl( clearQueue, jumpToEnd ){\n      var self = this;\n      var selfIsArrayLike = self.length !== undefined;\n      var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n      var cy = this._private.cy || this;\n\n      if( !cy.styleEnabled() ){ return this; }\n\n      for( var i = 0; i < all.length; i++ ){\n        var ele = all[i];\n        var _p = ele._private;\n        var anis = _p.animation.current;\n\n        for( var j = 0; j < anis.length; j++ ){\n          var ani = anis[j];\n          var ani_p = ani._private;\n\n          if( jumpToEnd ){\n            // next iteration of the animation loop, the animation\n            // will go straight to the end and be removed\n            ani_p.duration = 0;\n          }\n        }\n\n        // clear the queue of future animations\n        if( clearQueue ){\n          _p.animation.queue = [];\n        }\n\n        if( !jumpToEnd ){\n          _p.animation.current = [];\n        }\n      }\n\n      // we have to notify (the animation loop doesn't do it for us on `stop`)\n      cy.notify({\n        collection: this,\n        type: 'draw'\n      });\n\n      return this;\n    };\n  } // stop\n\n}; // define\n\nmodule.exports = define;\n","'use strict';\n\n// ref\n// https://github.com/jquery/jquery/blob/master/src/event.js\n\nvar Event = function( src, props ) {\n  // Allow instantiation without the 'new' keyword\n  if ( !(this instanceof Event) ) {\n    return new Event( src, props );\n  }\n\n  // Event object\n  if ( src && src.type ) {\n    this.originalEvent = src;\n    this.type = src.type;\n\n    // Events bubbling up the document may have been marked as prevented\n    // by a handler lower down the tree; reflect the correct value.\n    this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse;\n\n  // Event type\n  } else {\n    this.type = src;\n  }\n\n  // Put explicitly provided properties onto the event object\n  if ( props ) {\n    // util.extend( this, props );\n\n    // more efficient to manually copy fields we use\n    this.type = props.type !== undefined ? props.type : this.type;\n    this.cy = props.cy;\n    this.cyTarget = props.cyTarget;\n    this.cyPosition = props.cyPosition;\n    this.cyRenderedPosition = props.cyRenderedPosition;\n    this.namespace = props.namespace;\n    this.layout = props.layout;\n    this.data = props.data;\n    this.message = props.message;\n  }\n\n  // Create a timestamp if incoming event doesn't have one\n  this.timeStamp = src && src.timeStamp || Date.now();\n};\n\nfunction returnFalse() {\n  return false;\n}\n\nfunction returnTrue() {\n  return true;\n}\n\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\nEvent.prototype = {\n  instanceString: function(){\n    return 'event';\n  },\n\n  preventDefault: function() {\n    this.isDefaultPrevented = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n\n    // if preventDefault exists run it on the original event\n    if ( e.preventDefault ) {\n      e.preventDefault();\n    }\n  },\n\n  stopPropagation: function() {\n    this.isPropagationStopped = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n\n    // if stopPropagation exists run it on the original event\n    if ( e.stopPropagation ) {\n      e.stopPropagation();\n    }\n  },\n\n  stopImmediatePropagation: function() {\n    this.isImmediatePropagationStopped = returnTrue;\n    this.stopPropagation();\n  },\n\n  isDefaultPrevented: returnFalse,\n  isPropagationStopped: returnFalse,\n  isImmediatePropagationStopped: returnFalse\n};\n\nmodule.exports = Event;\n","'use strict';\n\nvar util = require('./util');\nvar define = require('./define');\nvar Collection = require('./collection');\nvar Core = require('./core');\nvar incExts = require('./extensions');\nvar is = require('./is');\n\n// registered extensions to cytoscape, indexed by name\nvar extensions = {};\n\n// registered modules for extensions, indexed by name\nvar modules = {};\n\nfunction setExtension( type, name, registrant ){\n\n  var ext = registrant;\n\n  if( type === 'core' ){\n    Core.prototype[ name ] = registrant;\n\n  } else if( type === 'collection' ){\n    Collection.prototype[ name ] = registrant;\n\n  } else if( type === 'layout' ){\n    // fill in missing layout functions in the prototype\n\n    var Layout = function( options ){\n      this.options = options;\n\n      registrant.call( this, options );\n\n      // make sure layout has _private for use w/ std apis like .on()\n      if( !is.plainObject(this._private) ){\n        this._private = {};\n      }\n\n      this._private.cy = options.cy;\n      this._private.listeners = [];\n    };\n\n    var layoutProto = Layout.prototype = Object.create( registrant.prototype );\n\n    var optLayoutFns = [];\n\n    for( var i = 0; i < optLayoutFns.length; i++ ){\n      var fnName = optLayoutFns[i];\n\n      layoutProto[fnName] = layoutProto[fnName] || function(){ return this; };\n    }\n\n    // either .start() or .run() is defined, so autogen the other\n    if( layoutProto.start && !layoutProto.run ){\n      layoutProto.run = function(){ this.start(); return this; };\n    } else if( !layoutProto.start && layoutProto.run ){\n      layoutProto.start = function(){ this.run(); return this; };\n    }\n\n    if( !layoutProto.stop ){\n      layoutProto.stop = function(){\n        var opts = this.options;\n\n        if( opts && opts.animate ){\n          var anis = this.animations;\n          for( var i = 0; i < anis.length; i++ ){\n            anis[i].stop();\n          }\n        }\n\n        this.trigger('layoutstop');\n\n        return this;\n      };\n    }\n\n    if( !layoutProto.destroy ){\n      layoutProto.destroy = function(){\n        return this;\n      };\n    }\n\n    layoutProto.on = define.on({ layout: true });\n    layoutProto.one = define.on({ layout: true, unbindSelfOnTrigger: true });\n    layoutProto.once = define.on({ layout: true, unbindAllBindersOnTrigger: true });\n    layoutProto.off = define.off({ layout: true });\n    layoutProto.trigger = define.trigger({ layout: true });\n\n    define.eventAliasesOn( layoutProto );\n\n    ext = Layout; // replace with our wrapped layout\n\n  } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){\n    // user registered renderers inherit from base\n\n    var bProto = getExtension( 'renderer', 'base' ).prototype;\n    var rProto = registrant.prototype;\n\n    for( var pName in bProto ){\n      var pVal = bProto[ pName ];\n      var existsInR = rProto[ pName ] != null;\n\n      if( existsInR ){\n        util.error('Can not register renderer `' + name + '` since it overrides `' + pName + '` in its prototype');\n        return;\n      }\n\n      rProto[ pName ] = pVal; // take impl from base\n    }\n\n    bProto.clientFunctions.forEach(function( name ){\n      rProto[ name ] = rProto[ name ] || function(){\n        util.error('Renderer does not implement `renderer.' + name + '()` on its prototype');\n      };\n    });\n\n  }\n\n  return util.setMap({\n    map: extensions,\n    keys: [ type, name ],\n    value: ext\n  });\n}\n\nfunction getExtension(type, name){\n  return util.getMap({\n    map: extensions,\n    keys: [ type, name ]\n  });\n}\n\nfunction setModule(type, name, moduleType, moduleName, registrant){\n  return util.setMap({\n    map: modules,\n    keys: [ type, name, moduleType, moduleName ],\n    value: registrant\n  });\n}\n\nfunction getModule(type, name, moduleType, moduleName){\n  return util.getMap({\n    map: modules,\n    keys: [ type, name, moduleType, moduleName ]\n  });\n}\n\nvar extension = function(){\n  // e.g. extension('renderer', 'svg')\n  if( arguments.length === 2 ){\n    return getExtension.apply(null, arguments);\n  }\n\n  // e.g. extension('renderer', 'svg', { ... })\n  else if( arguments.length === 3 ){\n    return setExtension.apply(null, arguments);\n  }\n\n  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')\n  else if( arguments.length === 4 ){\n    return getModule.apply(null, arguments);\n  }\n\n  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })\n  else if( arguments.length === 5 ){\n    return setModule.apply(null, arguments);\n  }\n\n  else {\n    util.error('Invalid extension access syntax');\n  }\n\n};\n\n// allows a core instance to access extensions internally\nCore.prototype.extension = extension;\n\n// included extensions\nincExts.forEach(function( group ){\n  group.extensions.forEach(function( ext ){\n    setExtension( group.type, ext.name, ext.impl );\n  });\n});\n\nmodule.exports = extension;\n","'use strict';\n\nmodule.exports = [\n  {\n    type: 'layout',\n    extensions: require('./layout')\n  },\n\n  {\n    type: 'renderer',\n    extensions: require('./renderer')\n  }\n];\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\nvar is = require('../../is');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)\n  padding: 30, // padding on fit\n  circle: false, // put depths in concentric circles if true, put depths top down if false\n  spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap)\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n  roots: undefined, // the roots of the trees\n  maximalAdjustments: 0, // how many times to try to position the nodes in a maximal way (i.e. no backtracking)\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction BreadthFirstLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nBreadthFirstLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var cy = params.cy;\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n  var graph = eles;\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var roots;\n  if( is.elementOrCollection(options.roots) ){\n    roots = options.roots;\n  } else if( is.array(options.roots) ){\n    var rootsArray = [];\n\n    for( var i = 0; i < options.roots.length; i++ ){\n      var id = options.roots[i];\n      var ele = cy.getElementById( id );\n      rootsArray.push( ele );\n    }\n\n    roots = cy.collection( rootsArray );\n  } else if( is.string(options.roots) ){\n    roots = cy.$( options.roots );\n\n  } else {\n    if( options.directed ){\n      roots = nodes.roots();\n    } else {\n      var components = [];\n      var unhandledNodes = nodes;\n\n      while( unhandledNodes.length > 0 ){\n        var currComp = cy.collection();\n\n        eles.bfs({\n          roots: unhandledNodes[0],\n          visit: function(i, depth, node, edge, pNode){\n            currComp = currComp.add( node );\n          },\n          directed: false\n        });\n\n        unhandledNodes = unhandledNodes.not( currComp );\n        components.push( currComp );\n      }\n\n      roots = cy.collection();\n      for( var i = 0; i < components.length; i++ ){\n        var comp = components[i];\n        var maxDegree = comp.maxDegree( false );\n        var compRoots = comp.filter(function(){\n          return this.degree(false) === maxDegree;\n        });\n\n        roots = roots.add( compRoots );\n      }\n\n    }\n  }\n\n\n  var depths = [];\n  var foundByBfs = {};\n  var id2depth = {};\n  var prevNode = {};\n  var prevEdge = {};\n  var successors = {};\n\n  // find the depths of the nodes\n  graph.bfs({\n    roots: roots,\n    directed: options.directed,\n    visit: function(i, depth, node, edge, pNode){\n      var ele = this[0];\n      var id = ele.id();\n\n      if( !depths[depth] ){\n        depths[depth] = [];\n      }\n\n      depths[depth].push( ele );\n      foundByBfs[ id ] = true;\n      id2depth[ id ] = depth;\n      prevNode[ id ] = pNode;\n      prevEdge[ id ] = edge;\n\n      if( pNode ){\n        var prevId = pNode.id();\n        var succ = successors[ prevId ] = successors[ prevId ] || [];\n\n        succ.push( node );\n      }\n    }\n  });\n\n  // check for nodes not found by bfs\n  var orphanNodes = [];\n  for( var i = 0; i < nodes.length; i++ ){\n    var ele = nodes[i];\n\n    if( foundByBfs[ ele.id() ] ){\n      continue;\n    } else {\n      orphanNodes.push( ele );\n    }\n  }\n\n  // assign orphan nodes a depth from their neighborhood\n  var maxChecks = orphanNodes.length * 3;\n  var checks = 0;\n  while( orphanNodes.length !== 0 && checks < maxChecks ){\n    var node = orphanNodes.shift();\n    var neighbors = node.neighborhood().nodes();\n    var assignedDepth = false;\n\n    for( var i = 0; i < neighbors.length; i++ ){\n      var depth = id2depth[ neighbors[i].id() ];\n\n      if( depth !== undefined ){\n        depths[depth].push( node );\n        assignedDepth = true;\n        break;\n      }\n    }\n\n    if( !assignedDepth ){\n      orphanNodes.push( node );\n    }\n\n    checks++;\n  }\n\n  // assign orphan nodes that are still left to the depth of their subgraph\n  while( orphanNodes.length !== 0 ){\n    var node = orphanNodes.shift();\n    //var subgraph = graph.bfs( node ).path;\n    var assignedDepth = false;\n\n    // for( var i = 0; i < subgraph.length; i++ ){\n    //   var depth = id2depth[ subgraph[i].id() ];\n\n    //   if( depth !== undefined ){\n    //     depths[depth].push( node );\n    //     assignedDepth = true;\n    //     break;\n    //   }\n    // }\n\n    if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0\n      if( depths.length === 0 ){\n        depths.push([]);\n      }\n\n      depths[0].push( node );\n    }\n  }\n\n  // assign the nodes a depth and index\n  var assignDepthsToEles = function(){\n    for( var i = 0; i < depths.length; i++ ){\n      var eles = depths[i];\n\n      for( var j = 0; j < eles.length; j++ ){\n        var ele = eles[j];\n\n        ele._private.scratch.breadthfirst = {\n          depth: i,\n          index: j\n        };\n      }\n    }\n  };\n  assignDepthsToEles();\n\n\n  var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth\n    var edges = node.connectedEdges(function(){\n      return this.data('target') === node.id();\n    });\n    var thisInfo = node._private.scratch.breadthfirst;\n    var highestDepthOfOther = 0;\n    var highestOther;\n    for( var i = 0; i < edges.length; i++ ){\n      var edge = edges[i];\n      var otherNode = edge.source()[0];\n      var otherInfo = otherNode._private.scratch.breadthfirst;\n\n      if( thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth ){\n        highestDepthOfOther = otherInfo.depth;\n        highestOther = otherNode;\n      }\n    }\n\n    return highestOther;\n  };\n\n   // make maximal if so set by adjusting depths\n  for( var adj = 0; adj < options.maximalAdjustments; adj++ ){\n\n    var nDepths = depths.length;\n    var elesToMove = [];\n    for( var i = 0; i < nDepths; i++ ){\n      var depth = depths[i];\n\n      var nDepth = depth.length;\n      for( var j = 0; j < nDepth; j++ ){\n        var ele = depth[j];\n        var info = ele._private.scratch.breadthfirst;\n        var intEle = intersectsDepth(ele);\n\n        if( intEle ){\n          info.intEle = intEle;\n          elesToMove.push( ele );\n        }\n      }\n    }\n\n    for( var i = 0; i < elesToMove.length; i++ ){\n      var ele = elesToMove[i];\n      var info = ele._private.scratch.breadthfirst;\n      var intEle = info.intEle;\n      var intInfo = intEle._private.scratch.breadthfirst;\n\n      depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index\n\n      // add to end of new depth\n      var newDepth = intInfo.depth + 1;\n      while( newDepth > depths.length - 1 ){\n        depths.push([]);\n      }\n      depths[ newDepth ].push( ele );\n\n      info.depth = newDepth;\n      info.index = depths[newDepth].length - 1;\n    }\n\n    assignDepthsToEles();\n  }\n\n  // find min distance we need to leave between nodes\n  var minDistance = 0;\n  if( options.avoidOverlap ){\n    for( var i = 0; i < nodes.length; i++ ){\n      var n = nodes[i];\n      var nbb = n.boundingBox();\n      var w = nbb.w;\n      var h = nbb.h;\n\n      minDistance = Math.max(minDistance, w, h);\n    }\n    minDistance *= options.spacingFactor; // just to have some nice spacing\n  }\n\n  // get the weighted percent for an element based on its connectivity to other levels\n  var cachedWeightedPercent = {};\n  var getWeightedPercent = function( ele ){\n    if( cachedWeightedPercent[ ele.id() ] ){\n      return cachedWeightedPercent[ ele.id() ];\n    }\n\n    var eleDepth = ele._private.scratch.breadthfirst.depth;\n    var neighbors = ele.neighborhood().nodes().not(':parent');\n    var percent = 0;\n    var samples = 0;\n\n    for( var i = 0; i < neighbors.length; i++ ){\n      var neighbor = neighbors[i];\n      var bf = neighbor._private.scratch.breadthfirst;\n      var index = bf.index;\n      var depth = bf.depth;\n      var nDepth = depths[depth].length;\n\n      if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above\n        percent += index / nDepth;\n        samples++;\n      }\n    }\n\n    samples = Math.max(1, samples);\n    percent = percent / samples;\n\n    if( samples === 0 ){ // so lone nodes have a \"don't care\" state in sorting\n      percent = undefined;\n    }\n\n    cachedWeightedPercent[ ele.id() ] = percent;\n    return percent;\n  };\n\n\n  // rearrange the indices in each depth level based on connectivity\n\n  var sortFn = function(a, b){\n    var apct = getWeightedPercent( a );\n    var bpct = getWeightedPercent( b );\n\n    return apct - bpct;\n  };\n\n  for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result\n\n    for( var i = 0; i < depths.length; i++ ){\n      depths[i] = depths[i].sort( sortFn );\n    }\n    assignDepthsToEles(); // and update\n\n  }\n\n  var biggestDepthSize = 0;\n  for( var i = 0; i < depths.length; i++ ){\n    biggestDepthSize = Math.max( depths[i].length, biggestDepthSize );\n  }\n\n  var center = {\n    x: bb.x1 + bb.w/2,\n    y: bb.x1 + bb.h/2\n  };\n\n  var getPosition = function( ele, isBottomDepth ){\n    var info = ele._private.scratch.breadthfirst;\n    var depth = info.depth;\n    var index = info.index;\n    var depthSize = depths[depth].length;\n\n    var distanceX = Math.max( bb.w / (depthSize + 1), minDistance );\n    var distanceY = Math.max( bb.h / (depths.length + 1), minDistance );\n    var radiusStepSize = Math.min( bb.w / 2 / depths.length, bb.h / 2 / depths.length );\n    radiusStepSize = Math.max( radiusStepSize, minDistance );\n\n    if( !options.circle ){\n\n      var epos = {\n        x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,\n        y: (depth + 1) * distanceY\n      };\n\n      if( isBottomDepth ){\n        return epos;\n      }\n\n      // var succs = successors[ ele.id() ];\n      // if( succs ){\n      //   epos.x = 0;\n      //\n      //   for( var i = 0 ; i < succs.length; i++ ){\n      //     var spos = pos[ succs[i].id() ];\n      //\n      //     epos.x += spos.x;\n      //   }\n      //\n      //   epos.x /= succs.length;\n      // } else {\n      //   //debugger;\n      // }\n\n      return epos;\n\n    } else {\n      if( options.circle ){\n        var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize/2 : 0);\n        var theta = 2 * Math.PI / depths[depth].length * index;\n\n        if( depth === 0 && depths[0].length === 1 ){\n          radius = 1;\n        }\n\n        return {\n          x: center.x + radius * Math.cos(theta),\n          y: center.y + radius * Math.sin(theta)\n        };\n\n      } else {\n        return {\n          x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,\n          y: (depth + 1) * distanceY\n        };\n      }\n    }\n\n  };\n\n  // get positions in reverse depth order\n  var pos = {};\n  for( var i = depths.length - 1; i >=0; i-- ){\n    var depth = depths[i];\n\n    for( var j = 0; j < depth.length; j++ ){\n      var node = depth[j];\n\n      pos[ node.id() ] = getPosition( node, i === depths.length - 1 );\n    }\n  }\n\n  nodes.layoutPositions(this, options, function(){\n    return pos[ this.id() ];\n  });\n\n  return this; // chaining\n};\n\nmodule.exports = BreadthFirstLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\nvar is = require('../../is');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  padding: 30, // the padding on fit\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space\n  radius: undefined, // the radius of the circle\n  startAngle: 3/2 * Math.PI, // where nodes start in radians\n  sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)\n  clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n  sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction CircleLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nCircleLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var cy = params.cy;\n  var eles = options.eles;\n\n  var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n\n  var nodes = eles.nodes().not(':parent');\n\n  if( options.sort ){\n    nodes = nodes.sort( options.sort );\n  }\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var center = {\n    x: bb.x1 + bb.w/2,\n    y: bb.y1 + bb.h/2\n  };\n\n  var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/nodes.length : options.sweep;\n\n  var dTheta = sweep / ( Math.max(1, nodes.length - 1) );\n  var r;\n\n  var minDistance = 0;\n  for( var i = 0; i < nodes.length; i++ ){\n    var n = nodes[i];\n    var nbb = n.boundingBox();\n    var w = nbb.w;\n    var h = nbb.h;\n\n    minDistance = Math.max(minDistance, w, h);\n  }\n\n  if( is.number(options.radius) ){\n    r = options.radius;\n  } else if( nodes.length <= 1 ){\n    r = 0;\n  } else {\n    r = Math.min( bb.h, bb.w )/2 - minDistance;\n  }\n\n  // calculate the radius\n  if( nodes.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)\n    minDistance *= 1.75; // just to have some nice spacing\n\n    var dcos = Math.cos(dTheta) - Math.cos(0);\n    var dsin = Math.sin(dTheta) - Math.sin(0);\n    var rMin = Math.sqrt( minDistance * minDistance / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping\n    r = Math.max( rMin, r );\n  }\n\n  var getPos = function( i, ele ){\n    var theta = options.startAngle + i * dTheta * ( clockwise ? 1 : -1 );\n\n    var rx = r * Math.cos( theta );\n    var ry = r * Math.sin( theta );\n    var pos = {\n      x: center.x + rx,\n      y: center.y + ry\n    };\n\n    return pos;\n  };\n\n  nodes.layoutPositions( this, options, getPos );\n\n  return this; // chaining\n};\n\nmodule.exports = CircleLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  padding: 30, // the padding on fit\n  startAngle: 3/2 * Math.PI, // where nodes start in radians\n  sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)\n  clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n  equidistant: false, // whether levels have an equal radial distance betwen them, may cause bounding box overflow\n  minNodeSpacing: 10, // min spacing between outside of nodes (used for radius adjustment)\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n  height: undefined, // height of layout area (overrides container height)\n  width: undefined, // width of layout area (overrides container width)\n  concentric: function(node){ // returns numeric value for each node, placing higher nodes in levels towards the centre\n    return node.degree();\n  },\n  levelWidth: function(nodes){ // the variation of concentric values in each level\n    return nodes.maxDegree() / 4;\n  },\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction ConcentricLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nConcentricLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n\n  var cy = params.cy;\n\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var center = {\n    x: bb.x1 + bb.w/2,\n    y: bb.y1 + bb.h/2\n  };\n\n  var nodeValues = []; // { node, value }\n  var theta = options.startAngle;\n  var maxNodeSize = 0;\n\n  for( var i = 0; i < nodes.length; i++ ){\n    var node = nodes[i];\n    var value;\n\n    // calculate the node value\n    value = options.concentric.apply(node, [ node ]);\n    nodeValues.push({\n      value: value,\n      node: node\n    });\n\n    // for style mapping\n    node._private.scratch.concentric = value;\n  }\n\n  // in case we used the `concentric` in style\n  nodes.updateStyle();\n\n  // calculate max size now based on potentially updated mappers\n  for( var i = 0; i < nodes.length; i++ ){\n    var node = nodes[i];\n    var nbb = node.boundingBox();\n\n    maxNodeSize = Math.max( maxNodeSize, nbb.w, nbb.h );\n  }\n\n  // sort node values in descreasing order\n  nodeValues.sort(function(a, b){\n    return b.value - a.value;\n  });\n\n  var levelWidth = options.levelWidth( nodes );\n\n  // put the values into levels\n  var levels = [ [] ];\n  var currentLevel = levels[0];\n  for( var i = 0; i < nodeValues.length; i++ ){\n    var val = nodeValues[i];\n\n    if( currentLevel.length > 0 ){\n      var diff = Math.abs( currentLevel[0].value - val.value );\n\n      if( diff >= levelWidth ){\n        currentLevel = [];\n        levels.push( currentLevel );\n      }\n    }\n\n    currentLevel.push( val );\n  }\n\n  // create positions from levels\n\n  var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes\n\n  if( !options.avoidOverlap ){ // then strictly constrain to bb\n    var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1;\n    var maxR = ( Math.min(bb.w, bb.h) / 2 - minDist );\n    var rStep = maxR / ( levels.length + firstLvlHasMulti ? 1 : 0 );\n\n    minDist = Math.min( minDist, rStep );\n  }\n\n  // find the metrics for each level\n  var r = 0;\n  for( var i = 0; i < levels.length; i++ ){\n    var level = levels[i];\n    var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/level.length : options.sweep;\n    var dTheta = level.dTheta = sweep / ( Math.max(1, level.length - 1) );\n\n    // calculate the radius\n    if( level.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)\n      var dcos = Math.cos(dTheta) - Math.cos(0);\n      var dsin = Math.sin(dTheta) - Math.sin(0);\n      var rMin = Math.sqrt( minDist * minDist / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping\n\n      r = Math.max( rMin, r );\n    }\n\n    level.r = r;\n\n    r += minDist;\n  }\n\n  if( options.equidistant ){\n    var rDeltaMax = 0;\n    var r = 0;\n\n    for( var i = 0; i < levels.length; i++ ){\n      var level = levels[i];\n      var rDelta = level.r - r;\n\n      rDeltaMax = Math.max( rDeltaMax, rDelta );\n    }\n\n    r = 0;\n    for( var i = 0; i < levels.length; i++ ){\n      var level = levels[i];\n\n      if( i === 0 ){\n        r = level.r;\n      }\n\n      level.r = r;\n\n      r += rDeltaMax;\n    }\n  }\n\n  // calculate the node positions\n  var pos = {}; // id => position\n  for( var i = 0; i < levels.length; i++ ){\n    var level = levels[i];\n    var dTheta = level.dTheta;\n    var r = level.r;\n\n    for( var j = 0; j < level.length; j++ ){\n      var val = level[j];\n      var theta = options.startAngle + (clockwise ? 1 : -1) * dTheta * j;\n\n      var p = {\n        x: center.x + r * Math.cos(theta),\n        y: center.y + r * Math.sin(theta)\n      };\n\n      pos[ val.node.id() ] = p;\n    }\n  }\n\n  // position the nodes\n  nodes.layoutPositions(this, options, function(){\n    var id = this.id();\n\n    return pos[id];\n  });\n\n  return this; // chaining\n};\n\nmodule.exports = ConcentricLayout;\n","'use strict';\n\n/*\nThe CoSE layout was written by Gerardo Huck.\nhttps://www.linkedin.com/in/gerardohuck/\n\nBased on the following article:\nhttp://dl.acm.org/citation.cfm?id=1498047\n\nModifications tracked on Github.\n*/\n\nvar util = require('../../util');\nvar math = require('../../math');\nvar Thread = require('../../thread');\nvar is = require('../../is');\n\nvar DEBUG;\n\n/**\n * @brief :  default layout options\n */\nvar defaults = {\n  // Called on `layoutready`\n  ready               : function() {},\n\n  // Called on `layoutstop`\n  stop                : function() {},\n\n  // Whether to animate while running the layout\n  animate             : true,\n\n  // The layout animates only after this many milliseconds\n  // (prevents flashing on fast runs)\n  animationThreshold  : 250,\n\n  // Number of iterations between consecutive screen positions update\n  // (0 -> only updated on the end)\n  refresh             : 20,\n\n  // Whether to fit the network view after when done\n  fit                 : true,\n\n  // Padding on fit\n  padding             : 30,\n\n  // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  boundingBox         : undefined,\n\n  // Extra spacing between components in non-compound graphs\n  componentSpacing    : 100,\n\n  // Node repulsion (non overlapping) multiplier\n  nodeRepulsion       : function( node ){ return 400000; },\n\n  // Node repulsion (overlapping) multiplier\n  nodeOverlap         : 10,\n\n  // Ideal edge (non nested) length\n  idealEdgeLength     : function( edge ){ return 10; },\n\n  // Divisor to compute edge forces\n  edgeElasticity      : function( edge ){ return 100; },\n\n  // Nesting factor (multiplier) to compute ideal edge length for nested edges\n  nestingFactor       : 5,\n\n  // Gravity force (constant)\n  gravity             : 80,\n\n  // Maximum number of iterations to perform\n  numIter             : 1000,\n\n  // Initial temperature (maximum node displacement)\n  initialTemp         : 200,\n\n  // Cooling factor (how the temperature is reduced between consecutive iterations\n  coolingFactor       : 0.95,\n\n  // Lower temperature threshold (below this point the layout will end)\n  minTemp             : 1.0,\n\n  // Whether to use threading to speed up the layout\n  useMultitasking     : true\n};\n\n\n/**\n * @brief       : constructor\n * @arg options : object containing layout options\n */\nfunction CoseLayout(options) {\n  this.options = util.extend({}, defaults, options);\n\n  this.options.layout = this;\n}\n\n\n/**\n * @brief : runs the layout\n */\nCoseLayout.prototype.run = function() {\n  var options = this.options;\n  var cy      = options.cy;\n  var layout  = this;\n  var thread  = this.thread;\n\n  if( !thread || thread.stopped() ){\n    thread = this.thread = Thread({ disabled: !options.useMultitasking });\n  }\n\n  layout.stopped = false;\n\n  layout.trigger({ type: 'layoutstart', layout: layout });\n\n  // Set DEBUG - Global variable\n  if (true === options.debug) {\n    DEBUG = true;\n  } else {\n    DEBUG = false;\n  }\n\n  // Initialize layout info\n  var layoutInfo = createLayoutInfo(cy, layout, options);\n\n  // Show LayoutInfo contents if debugging\n  if (DEBUG) {\n    printLayoutInfo(layoutInfo);\n  }\n\n  // If required, randomize node positions\n  // if (true === options.randomize) {\n    randomizePositions(layoutInfo, cy);\n  // }\n\n  var startTime = Date.now();\n  var refreshRequested = false;\n  var refresh = function( rOpts ){\n    rOpts = rOpts || {};\n\n    if( refreshRequested ){\n      return;\n    }\n\n    if( !rOpts.force && Date.now() - startTime < options.animationThreshold ){\n      return;\n    }\n\n    refreshRequested = true;\n\n    util.requestAnimationFrame(function(){\n      refreshPositions(layoutInfo, cy, options);\n\n      // Fit the graph if necessary\n      if (true === options.fit) {\n        cy.fit( options.padding );\n      }\n\n      refreshRequested = false;\n    });\n  };\n\n  thread.on('message', function( e ){\n    var layoutNodes = e.message;\n\n    layoutInfo.layoutNodes = layoutNodes;\n    refresh();\n  });\n\n  thread.pass({\n    layoutInfo: layoutInfo,\n    options: {\n      animate: options.animate,\n      refresh: options.refresh,\n      componentSpacing: options.componentSpacing,\n      nodeOverlap: options.nodeOverlap,\n      nestingFactor: options.nestingFactor,\n      gravity: options.gravity,\n      numIter: options.numIter,\n      initialTemp: options.initialTemp,\n      coolingFactor: options.coolingFactor,\n      minTemp: options.minTemp\n    }\n  }).run(function( pass ){\n    var layoutInfo = pass.layoutInfo;\n    var options = pass.options;\n    var stopped = false;\n\n    /**\n     * @brief          : Performs one iteration of the physical simulation\n     * @arg layoutInfo : LayoutInfo object already initialized\n     * @arg cy         : Cytoscape object\n     * @arg options    : Layout options\n     */\n    var step = function(layoutInfo, options, step) {\n      // var s = \"\\n\\n###############################\";\n      // s += \"\\nSTEP: \" + step;\n      // s += \"\\n###############################\\n\";\n      // logDebug(s);\n\n      // Calculate node repulsions\n      calculateNodeForces(layoutInfo, options);\n      // Calculate edge forces\n      calculateEdgeForces(layoutInfo, options);\n      // Calculate gravity forces\n      calculateGravityForces(layoutInfo, options);\n      // Propagate forces from parent to child\n      propagateForces(layoutInfo, options);\n      // Update positions based on calculated forces\n      updatePositions(layoutInfo, options);\n    };\n\n    /**\n     * @brief : Computes the node repulsion forces\n     */\n    var calculateNodeForces = function(layoutInfo, options) {\n      // Go through each of the graphs in graphSet\n      // Nodes only repel each other if they belong to the same graph\n      // var s = 'calculateNodeForces';\n      // logDebug(s);\n      for (var i = 0; i < layoutInfo.graphSet.length; i ++) {\n        var graph    = layoutInfo.graphSet[i];\n        var numNodes = graph.length;\n\n        // s = \"Set: \" + graph.toString();\n        // logDebug(s);\n\n        // Now get all the pairs of nodes\n        // Only get each pair once, (A, B) = (B, A)\n        for (var j = 0; j < numNodes; j++) {\n          var node1 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];\n\n          for (var k = j + 1; k < numNodes; k++) {\n            var node2 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[k]]];\n\n            nodeRepulsion(node1, node2, layoutInfo, options);\n          }\n        }\n      }\n    };\n\n    /**\n     * @brief : Compute the node repulsion forces between a pair of nodes\n     */\n    var nodeRepulsion = function(node1, node2, layoutInfo, options) {\n      // var s = \"Node repulsion. Node1: \" + node1.id + \" Node2: \" + node2.id;\n\n      var cmptId1 = node1.cmptId;\n      var cmptId2 = node2.cmptId;\n\n      if( cmptId1 !== cmptId2 && !layoutInfo.isCompound ){ return; }\n\n      // Get direction of line connecting both node centers\n      var directionX = node2.positionX - node1.positionX;\n      var directionY = node2.positionY - node1.positionY;\n      // s += \"\\ndirectionX: \" + directionX + \", directionY: \" + directionY;\n\n      // If both centers are the same, apply a random force\n      if (0 === directionX && 0 === directionY) {\n        // s += \"\\nNodes have the same position.\";\n        return; // TODO could be improved with random force\n      }\n\n      var overlap = nodesOverlap(node1, node2, directionX, directionY);\n\n      if (overlap > 0) {\n        // s += \"\\nNodes DO overlap.\";\n        // s += \"\\nOverlap: \" + overlap;\n        // If nodes overlap, repulsion force is proportional\n        // to the overlap\n        var force    = options.nodeOverlap * overlap;\n\n        // Compute the module and components of the force vector\n        var distance = Math.sqrt(directionX * directionX + directionY * directionY);\n        // s += \"\\nDistance: \" + distance;\n        var forceX   = force * directionX / distance;\n        var forceY   = force * directionY / distance;\n\n      } else {\n        // s += \"\\nNodes do NOT overlap.\";\n        // If there's no overlap, force is inversely proportional\n        // to squared distance\n\n        // Get clipping points for both nodes\n        var point1 = findClippingPoint(node1, directionX, directionY);\n        var point2 = findClippingPoint(node2, -1 * directionX, -1 * directionY);\n\n        // Use clipping points to compute distance\n        var distanceX   = point2.x - point1.x;\n        var distanceY   = point2.y - point1.y;\n        var distanceSqr = distanceX * distanceX + distanceY * distanceY;\n        var distance    = Math.sqrt(distanceSqr);\n        // s += \"\\nDistance: \" + distance;\n\n        // Compute the module and components of the force vector\n        var force  = ( node1.nodeRepulsion + node2.nodeRepulsion ) / distanceSqr;\n        var forceX = force * distanceX / distance;\n        var forceY = force * distanceY / distance;\n      }\n\n      // Apply force\n      if( !node1.isLocked ){\n        node1.offsetX -= forceX;\n        node1.offsetY -= forceY;\n      }\n\n      if( !node2.isLocked ){\n        node2.offsetX += forceX;\n        node2.offsetY += forceY;\n      }\n\n      // s += \"\\nForceX: \" + forceX + \" ForceY: \" + forceY;\n      // logDebug(s);\n\n      return;\n    };\n\n    /**\n     * @brief  : Determines whether two nodes overlap or not\n     * @return : Amount of overlapping (0 => no overlap)\n     */\n    var nodesOverlap = function(node1, node2, dX, dY) {\n\n      if (dX > 0) {\n        var overlapX = node1.maxX - node2.minX;\n      } else {\n        var overlapX = node2.maxX - node1.minX;\n      }\n\n      if (dY > 0) {\n        var overlapY = node1.maxY - node2.minY;\n      } else {\n        var overlapY = node2.maxY - node1.minY;\n      }\n\n      if (overlapX >= 0 && overlapY >= 0) {\n        return Math.sqrt(overlapX * overlapX + overlapY * overlapY);\n      } else {\n        return 0;\n      }\n    };\n\n    /**\n     * @brief : Finds the point in which an edge (direction dX, dY) intersects\n     *          the rectangular bounding box of it's source/target node\n     */\n    var findClippingPoint = function(node, dX, dY) {\n\n      // Shorcuts\n      var X = node.positionX;\n      var Y = node.positionY;\n      var H = node.height || 1;\n      var W = node.width || 1;\n      var dirSlope     = dY / dX;\n      var nodeSlope    = H / W;\n\n      // var s = 'Computing clipping point of node ' + node.id +\n      //   \" . Height:  \" + H + \", Width: \" + W +\n      //   \"\\nDirection \" + dX + \", \" + dY;\n      //\n      // Compute intersection\n      var res = {};\n      do {\n        // Case: Vertical direction (up)\n        if (0 === dX && 0 < dY) {\n          res.x = X;\n          // s += \"\\nUp direction\";\n          res.y = Y + H / 2;\n          break;\n        }\n\n        // Case: Vertical direction (down)\n        if (0 === dX && 0 > dY) {\n          res.x = X;\n          res.y = Y + H / 2;\n          // s += \"\\nDown direction\";\n          break;\n        }\n\n        // Case: Intersects the right border\n        if (0 < dX &&\n        -1 * nodeSlope <= dirSlope &&\n        dirSlope <= nodeSlope) {\n          res.x = X + W / 2;\n          res.y = Y + (W * dY / 2 / dX);\n          // s += \"\\nRightborder\";\n          break;\n        }\n\n        // Case: Intersects the left border\n        if (0 > dX &&\n        -1 * nodeSlope <= dirSlope &&\n        dirSlope <= nodeSlope) {\n          res.x = X - W / 2;\n          res.y = Y - (W * dY / 2 / dX);\n          // s += \"\\nLeftborder\";\n          break;\n        }\n\n        // Case: Intersects the top border\n        if (0 < dY &&\n        ( dirSlope <= -1 * nodeSlope ||\n          dirSlope >= nodeSlope )) {\n          res.x = X + (H * dX / 2 / dY);\n          res.y = Y + H / 2;\n          // s += \"\\nTop border\";\n          break;\n        }\n\n        // Case: Intersects the bottom border\n        if (0 > dY &&\n        ( dirSlope <= -1 * nodeSlope ||\n          dirSlope >= nodeSlope )) {\n          res.x = X - (H * dX / 2 / dY);\n          res.y = Y - H / 2;\n          // s += \"\\nBottom border\";\n          break;\n        }\n\n      } while (false);\n\n      // s += \"\\nClipping point found at \" + res.x + \", \" + res.y;\n      // logDebug(s);\n      return res;\n    };\n\n    /**\n     * @brief : Calculates all edge forces\n     */\n    var calculateEdgeForces = function(layoutInfo, options) {\n      // Iterate over all edges\n      for (var i = 0; i < layoutInfo.edgeSize; i++) {\n        // Get edge, source & target nodes\n        var edge     = layoutInfo.layoutEdges[i];\n        var sourceIx = layoutInfo.idToIndex[edge.sourceId];\n        var source   = layoutInfo.layoutNodes[sourceIx];\n        var targetIx = layoutInfo.idToIndex[edge.targetId];\n        var target   = layoutInfo.layoutNodes[targetIx];\n\n        // Get direction of line connecting both node centers\n        var directionX = target.positionX - source.positionX;\n        var directionY = target.positionY - source.positionY;\n\n        // If both centers are the same, do nothing.\n        // A random force has already been applied as node repulsion\n        if (0 === directionX && 0 === directionY) {\n        return;\n        }\n\n        // Get clipping points for both nodes\n        var point1 = findClippingPoint(source, directionX, directionY);\n        var point2 = findClippingPoint(target, -1 * directionX, -1 * directionY);\n\n\n        var lx = point2.x - point1.x;\n        var ly = point2.y - point1.y;\n        var l  = Math.sqrt(lx * lx + ly * ly);\n\n        var force  = Math.pow(edge.idealLength - l, 2) / edge.elasticity;\n\n        if (0 !== l) {\n          var forceX = force * lx / l;\n          var forceY = force * ly / l;\n        } else {\n          var forceX = 0;\n          var forceY = 0;\n        }\n\n        // Add this force to target and source nodes\n        if( !source.isLocked ){\n          source.offsetX += forceX;\n          source.offsetY += forceY;\n        }\n\n        if( !target.isLocked ){\n          target.offsetX -= forceX;\n          target.offsetY -= forceY;\n        }\n\n        // var s = 'Edge force between nodes ' + source.id + ' and ' + target.id;\n        // s += \"\\nDistance: \" + l + \" Force: (\" + forceX + \", \" + forceY + \")\";\n        // logDebug(s);\n      }\n    };\n\n    /**\n     * @brief : Computes gravity forces for all nodes\n     */\n    var calculateGravityForces = function(layoutInfo, options) {\n      var distThreshold = 1;\n\n      // var s = 'calculateGravityForces';\n      // logDebug(s);\n      for (var i = 0; i < layoutInfo.graphSet.length; i ++) {\n        var graph    = layoutInfo.graphSet[i];\n        var numNodes = graph.length;\n\n        // s = \"Set: \" + graph.toString();\n        // logDebug(s);\n\n        // Compute graph center\n        if (0 === i) {\n          var centerX   = layoutInfo.clientHeight / 2;\n          var centerY   = layoutInfo.clientWidth  / 2;\n        } else {\n          // Get Parent node for this graph, and use its position as center\n          var temp    = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[0]]];\n          var parent  = layoutInfo.layoutNodes[layoutInfo.idToIndex[temp.parentId]];\n          var centerX = parent.positionX;\n          var centerY = parent.positionY;\n        }\n        // s = \"Center found at: \" + centerX + \", \" + centerY;\n        // logDebug(s);\n\n        // Apply force to all nodes in graph\n        for (var j = 0; j < numNodes; j++) {\n          var node = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];\n          // s = \"Node: \" + node.id;\n\n          if( node.isLocked ){ continue; }\n\n          var dx = centerX - node.positionX;\n          var dy = centerY - node.positionY;\n          var d  = Math.sqrt(dx * dx + dy * dy);\n          if (d > distThreshold) {\n            var fx = options.gravity * dx / d;\n            var fy = options.gravity * dy / d;\n            node.offsetX += fx;\n            node.offsetY += fy;\n            // s += \": Applied force: \" + fx + \", \" + fy;\n          } else {\n            // s += \": skypped since it's too close to center\";\n          }\n          // logDebug(s);\n        }\n      }\n    };\n\n    /**\n     * @brief          : This function propagates the existing offsets from\n     *                   parent nodes to its descendents.\n     * @arg layoutInfo : layoutInfo Object\n     * @arg cy         : cytoscape Object\n     * @arg options    : Layout options\n     */\n    var propagateForces = function(layoutInfo, options) {\n      // Inline implementation of a queue, used for traversing the graph in BFS order\n      var queue = [];\n      var start = 0;   // Points to the start the queue\n      var end   = -1;  // Points to the end of the queue\n\n      // logDebug('propagateForces');\n\n      // Start by visiting the nodes in the root graph\n      queue.push.apply(queue, layoutInfo.graphSet[0]);\n      end += layoutInfo.graphSet[0].length;\n\n      // Traverse the graph, level by level,\n      while (start <= end) {\n        // Get the node to visit and remove it from queue\n        var nodeId    = queue[start++];\n        var nodeIndex = layoutInfo.idToIndex[nodeId];\n        var node      = layoutInfo.layoutNodes[nodeIndex];\n        var children  = node.children;\n\n        // We only need to process the node if it's compound\n        if (0 < children.length && !node.isLocked) {\n          var offX = node.offsetX;\n          var offY = node.offsetY;\n\n          // var s = \"Propagating offset from parent node : \" + node.id +\n          //   \". OffsetX: \" + offX + \". OffsetY: \" + offY;\n          // s += \"\\n Children: \" + children.toString();\n          // logDebug(s);\n\n          for (var i = 0; i < children.length; i++) {\n            var childNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[children[i]]];\n            // Propagate offset\n            childNode.offsetX += offX;\n            childNode.offsetY += offY;\n            // Add children to queue to be visited\n            queue[++end] = children[i];\n          }\n\n          // Reset parent offsets\n          node.offsetX = 0;\n          node.offsetY = 0;\n        }\n\n      }\n    };\n\n    /**\n     * @brief : Updates the layout model positions, based on\n     *          the accumulated forces\n     */\n    var updatePositions = function(layoutInfo, options) {\n      // var s = 'Updating positions';\n      // logDebug(s);\n\n      // Reset boundaries for compound nodes\n      for (var i = 0; i < layoutInfo.nodeSize; i++) {\n        var n = layoutInfo.layoutNodes[i];\n        if (0 < n.children.length) {\n          // logDebug(\"Resetting boundaries of compound node: \" + n.id);\n          n.maxX = undefined;\n          n.minX = undefined;\n          n.maxY = undefined;\n          n.minY = undefined;\n        }\n      }\n\n      for (var i = 0; i < layoutInfo.nodeSize; i++) {\n        var n = layoutInfo.layoutNodes[i];\n        if (0 < n.children.length || n.isLocked) {\n          // No need to set compound or locked node position\n          // logDebug(\"Skipping position update of node: \" + n.id);\n          continue;\n        }\n        // s = \"Node: \" + n.id + \" Previous position: (\" +\n        // n.positionX + \", \" + n.positionY + \").\";\n\n        // Limit displacement in order to improve stability\n        var tempForce = limitForce(n.offsetX, n.offsetY, layoutInfo.temperature);\n        n.positionX += tempForce.x;\n        n.positionY += tempForce.y;\n        n.offsetX = 0;\n        n.offsetY = 0;\n        n.minX    = n.positionX - n.width;\n        n.maxX    = n.positionX + n.width;\n        n.minY    = n.positionY - n.height;\n        n.maxY    = n.positionY + n.height;\n        // s += \" New Position: (\" + n.positionX + \", \" + n.positionY + \").\";\n        // logDebug(s);\n\n        // Update ancestry boudaries\n        updateAncestryBoundaries(n, layoutInfo);\n      }\n\n      // Update size, position of compund nodes\n      for (var i = 0; i < layoutInfo.nodeSize; i++) {\n        var n = layoutInfo.layoutNodes[i];\n        if ( 0 < n.children.length && !n.isLocked ) {\n          n.positionX = (n.maxX + n.minX) / 2;\n          n.positionY = (n.maxY + n.minY) / 2;\n          n.width     = n.maxX - n.minX;\n          n.height    = n.maxY - n.minY;\n          // s = \"Updating position, size of compound node \" + n.id;\n          // s += \"\\nPositionX: \" + n.positionX + \", PositionY: \" + n.positionY;\n          // s += \"\\nWidth: \" + n.width + \", Height: \" + n.height;\n          // logDebug(s);\n        }\n      }\n    };\n\n    /**\n     * @brief : Limits a force (forceX, forceY) to be not\n     *          greater (in modulo) than max.\n     8          Preserves force direction.\n     */\n    var limitForce = function(forceX, forceY, max) {\n      // var s = \"Limiting force: (\" + forceX + \", \" + forceY + \"). Max: \" + max;\n      var force = Math.sqrt(forceX * forceX + forceY * forceY);\n\n      if (force > max) {\n        var res = {\n        x : max * forceX / force,\n        y : max * forceY / force\n        };\n\n      } else {\n        var res = {\n        x : forceX,\n        y : forceY\n        };\n      }\n\n      // s += \".\\nResult: (\" + res.x + \", \" + res.y + \")\";\n      // logDebug(s);\n\n      return res;\n    };\n\n    /**\n     * @brief : Function used for keeping track of compound node\n     *          sizes, since they should bound all their subnodes.\n     */\n    var updateAncestryBoundaries = function(node, layoutInfo) {\n      // var s = \"Propagating new position/size of node \" + node.id;\n      var parentId = node.parentId;\n      if (null == parentId) {\n        // If there's no parent, we are done\n        // s += \". No parent node.\";\n        // logDebug(s);\n        return;\n      }\n\n      // Get Parent Node\n      var p = layoutInfo.layoutNodes[layoutInfo.idToIndex[parentId]];\n      var flag = false;\n\n      // MaxX\n      if (null == p.maxX || node.maxX + p.padRight > p.maxX) {\n        p.maxX = node.maxX + p.padRight;\n        flag = true;\n        // s += \"\\nNew maxX for parent node \" + p.id + \": \" + p.maxX;\n      }\n\n      // MinX\n      if (null == p.minX || node.minX - p.padLeft < p.minX) {\n        p.minX = node.minX - p.padLeft;\n        flag = true;\n        // s += \"\\nNew minX for parent node \" + p.id + \": \" + p.minX;\n      }\n\n      // MaxY\n      if (null == p.maxY || node.maxY + p.padBottom > p.maxY) {\n        p.maxY = node.maxY + p.padBottom;\n        flag = true;\n        // s += \"\\nNew maxY for parent node \" + p.id + \": \" + p.maxY;\n      }\n\n      // MinY\n      if (null == p.minY || node.minY - p.padTop < p.minY) {\n        p.minY = node.minY - p.padTop;\n        flag = true;\n        // s += \"\\nNew minY for parent node \" + p.id + \": \" + p.minY;\n      }\n\n      // If updated boundaries, propagate changes upward\n      if (flag) {\n        // logDebug(s);\n        return updateAncestryBoundaries(p, layoutInfo);\n      }\n\n      // s += \". No changes in boundaries/position of parent node \" + p.id;\n      // logDebug(s);\n      return;\n    };\n\n    var separateComponents = function(layutInfo, options){\n      var nodes = layoutInfo.layoutNodes;\n      var components = [];\n\n      for( var i = 0; i < nodes.length; i++ ){\n        var node = nodes[i];\n        var cid = node.cmptId;\n        var component = components[ cid ] = components[ cid ] || [];\n\n        component.push( node );\n      }\n\n      var totalA = 0;\n\n      for( var i = 0; i < components.length; i++ ){\n        var c = components[i];\n        c.x1 = Infinity;\n        c.x2 = -Infinity;\n        c.y1 = Infinity;\n        c.y2 = -Infinity;\n\n        for( var j = 0; j < c.length; j++ ){\n          var n = c[j];\n\n          c.x1 = Math.min( c.x1, n.positionX - n.width/2 );\n          c.x2 = Math.max( c.x2, n.positionX + n.width/2 );\n          c.y1 = Math.min( c.y1, n.positionY - n.height/2 );\n          c.y2 = Math.max( c.y2, n.positionY + n.height/2 );\n        }\n\n        c.w = c.x2 - c.x1;\n        c.h = c.y2 - c.y1;\n\n        totalA += c.w * c.h;\n      }\n\n      components.sort(function( c1, c2 ){\n        return c2.w*c2.h - c1.w*c1.h;\n      });\n\n      var x = 0;\n      var y = 0;\n      var usedW = 0;\n      var rowH = 0;\n      var maxRowW = Math.sqrt( totalA ) * layoutInfo.clientWidth / layoutInfo.clientHeight;\n\n      for( var i = 0; i < components.length; i++ ){\n        var c = components[i];\n\n        for( var j = 0; j < c.length; j++ ){\n          var n = c[j];\n\n          if( !n.isLocked ){\n            n.positionX += x;\n            n.positionY += y;\n          }\n        }\n\n        x += c.w + options.componentSpacing;\n        usedW += c.w + options.componentSpacing;\n        rowH = Math.max( rowH, c.h );\n\n        if( usedW > maxRowW ){\n          y += rowH + options.componentSpacing;\n          x = 0;\n          usedW = 0;\n          rowH = 0;\n        }\n      }\n    };\n\n    var mainLoop = function(i){\n      if( stopped ){\n        // logDebug(\"Layout manually stopped. Stopping computation in step \" + i);\n        return false;\n      }\n\n      // Do one step in the phisical simulation\n      step(layoutInfo, options, i);\n\n      // Update temperature\n      layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor;\n      // logDebug(\"New temperature: \" + layoutInfo.temperature);\n\n      if (layoutInfo.temperature < options.minTemp) {\n        // logDebug(\"Temperature drop below minimum threshold. Stopping computation in step \" + i);\n        return false;\n      }\n\n      return true;\n    };\n\n    var i = 0;\n    var loopRet;\n\n    do {\n      var f = 0;\n\n      while( f < options.refresh && i < options.numIter ){\n        var loopRet = mainLoop(i);\n        if( !loopRet ){ break; }\n\n        f++;\n        i++;\n      }\n\n      if( options.animate ){\n        broadcast( layoutInfo.layoutNodes ); // jshint ignore:line\n      }\n\n    } while ( loopRet && i + 1 < options.numIter );\n\n    separateComponents( layoutInfo, options );\n\n    return layoutInfo;\n  }).then(function( layoutInfoUpdated ){\n    layoutInfo.layoutNodes = layoutInfoUpdated.layoutNodes; // get the positions\n\n    thread.stop();\n    done();\n  });\n\n  var done = function(){\n    refresh({ force: true });\n\n    // Layout has finished\n    layout.one('layoutstop', options.stop);\n    layout.trigger({ type: 'layoutstop', layout: layout });\n  };\n\n  return this; // chaining\n};\n\n\n/**\n * @brief : called on continuous layouts to stop them before they finish\n */\nCoseLayout.prototype.stop = function(){\n  this.stopped = true;\n\n  if( this.thread ){\n    this.thread.stop();\n  }\n\n  this.trigger('layoutstop');\n\n  return this; // chaining\n};\n\nCoseLayout.prototype.destroy = function(){\n  if( this.thread ){\n    this.thread.stop();\n  }\n\n  return this; // chaining\n};\n\n\n/**\n * @brief     : Creates an object which is contains all the data\n *              used in the layout process\n * @arg cy    : cytoscape.js object\n * @return    : layoutInfo object initialized\n */\nvar createLayoutInfo = function(cy, layout, options) {\n  // Shortcut\n  var edges = options.eles.edges();\n  var nodes = options.eles.nodes();\n\n  var layoutInfo   = {\n    isCompound   : cy.hasCompoundNodes(),\n    layoutNodes  : [],\n    idToIndex    : {},\n    nodeSize     : nodes.size(),\n    graphSet     : [],\n    indexToGraph : [],\n    layoutEdges  : [],\n    edgeSize     : edges.size(),\n    temperature  : options.initialTemp,\n    clientWidth  : cy.width(),\n    clientHeight : cy.width(),\n    boundingBox  : math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n                     x1: 0, y1: 0, w: cy.width(), h: cy.height()\n                   } )\n  };\n\n  var components = options.eles.components();\n  var id2cmptId = {};\n\n  for( var i = 0; i < components.length; i++ ){\n    var component = components[i];\n\n    for( var j = 0; j < component.length; j++ ){\n      var node = component[j];\n\n      id2cmptId[ node.id() ] = i;\n    }\n  }\n\n  // Iterate over all nodes, creating layout nodes\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = nodes[i];\n    var nbb = n.boundingBox();\n\n    var tempNode        = {};\n    tempNode.isLocked   = n.locked();\n    tempNode.id         = n.data('id');\n    tempNode.parentId   = n.data('parent');\n    tempNode.cmptId     = id2cmptId[ n.id() ];\n    tempNode.children   = [];\n    tempNode.positionX  = n.position('x');\n    tempNode.positionY  = n.position('y');\n    tempNode.offsetX    = 0;\n    tempNode.offsetY    = 0;\n    tempNode.height     = nbb.w;\n    tempNode.width      = nbb.h;\n    tempNode.maxX       = tempNode.positionX + tempNode.width  / 2;\n    tempNode.minX       = tempNode.positionX - tempNode.width  / 2;\n    tempNode.maxY       = tempNode.positionY + tempNode.height / 2;\n    tempNode.minY       = tempNode.positionY - tempNode.height / 2;\n    tempNode.padLeft    = parseFloat( n.style('padding-left') );\n    tempNode.padRight   = parseFloat( n.style('padding-right') );\n    tempNode.padTop     = parseFloat( n.style('padding-top') );\n    tempNode.padBottom  = parseFloat( n.style('padding-bottom') );\n\n    // forces\n    tempNode.nodeRepulsion = is.fn( options.nodeRepulsion ) ? options.nodeRepulsion.call( n, n ) : options.nodeRepulsion;\n\n    // Add new node\n    layoutInfo.layoutNodes.push(tempNode);\n    // Add entry to id-index map\n    layoutInfo.idToIndex[tempNode.id] = i;\n  }\n\n  // Inline implementation of a queue, used for traversing the graph in BFS order\n  var queue = [];\n  var start = 0;   // Points to the start the queue\n  var end   = -1;  // Points to the end of the queue\n\n  var tempGraph = [];\n\n  // Second pass to add child information and\n  // initialize queue for hierarchical traversal\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = layoutInfo.layoutNodes[i];\n    var p_id = n.parentId;\n    // Check if node n has a parent node\n    if (null != p_id) {\n    // Add node Id to parent's list of children\n    layoutInfo.layoutNodes[layoutInfo.idToIndex[p_id]].children.push(n.id);\n    } else {\n    // If a node doesn't have a parent, then it's in the root graph\n    queue[++end] = n.id;\n    tempGraph.push(n.id);\n    }\n  }\n\n  // Add root graph to graphSet\n  layoutInfo.graphSet.push(tempGraph);\n\n  // Traverse the graph, level by level,\n  while (start <= end) {\n    // Get the node to visit and remove it from queue\n    var node_id  = queue[start++];\n    var node_ix  = layoutInfo.idToIndex[node_id];\n    var node     = layoutInfo.layoutNodes[node_ix];\n    var children = node.children;\n    if (children.length > 0) {\n    // Add children nodes as a new graph to graph set\n    layoutInfo.graphSet.push(children);\n    // Add children to que queue to be visited\n    for (var i = 0; i < children.length; i++) {\n      queue[++end] = children[i];\n    }\n    }\n  }\n\n  // Create indexToGraph map\n  for (var i = 0; i < layoutInfo.graphSet.length; i++) {\n    var graph = layoutInfo.graphSet[i];\n    for (var j = 0; j < graph.length; j++) {\n    var index = layoutInfo.idToIndex[graph[j]];\n    layoutInfo.indexToGraph[index] = i;\n    }\n  }\n\n  // Iterate over all edges, creating Layout Edges\n  for (var i = 0; i < layoutInfo.edgeSize; i++) {\n    var e = edges[i];\n    var tempEdge = {};\n    tempEdge.id       = e.data('id');\n    tempEdge.sourceId = e.data('source');\n    tempEdge.targetId = e.data('target');\n\n    // Compute ideal length\n    var idealLength = is.fn( options.idealEdgeLength ) ? options.idealEdgeLength.call( e, e ) : options.idealEdgeLength;\n    var elasticity = is.fn( options.edgeElasticity ) ? options.edgeElasticity.call( e, e ) : options.edgeElasticity;\n\n    // Check if it's an inter graph edge\n    var sourceIx    = layoutInfo.idToIndex[tempEdge.sourceId];\n    var targetIx    = layoutInfo.idToIndex[tempEdge.targetId];\n    var sourceGraph = layoutInfo.indexToGraph[sourceIx];\n    var targetGraph = layoutInfo.indexToGraph[targetIx];\n\n    if (sourceGraph != targetGraph) {\n      // Find lowest common graph ancestor\n      var lca = findLCA(tempEdge.sourceId, tempEdge.targetId, layoutInfo);\n\n      // Compute sum of node depths, relative to lca graph\n      var lcaGraph = layoutInfo.graphSet[lca];\n      var depth    = 0;\n\n      // Source depth\n      var tempNode = layoutInfo.layoutNodes[sourceIx];\n      while ( -1 === lcaGraph.indexOf(tempNode.id) ) {\n        tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n        depth++;\n      }\n\n      // Target depth\n      tempNode = layoutInfo.layoutNodes[targetIx];\n      while ( -1 === lcaGraph.indexOf(tempNode.id) ) {\n        tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n        depth++;\n      }\n\n      // logDebug('LCA of nodes ' + tempEdge.sourceId + ' and ' + tempEdge.targetId +\n        //  \". Index: \" + lca + \" Contents: \" + lcaGraph.toString() +\n        //  \". Depth: \" + depth);\n\n      // Update idealLength\n      idealLength *= depth * options.nestingFactor;\n    }\n\n    tempEdge.idealLength = idealLength;\n    tempEdge.elasticity = elasticity;\n\n    layoutInfo.layoutEdges.push(tempEdge);\n  }\n\n  // Finally, return layoutInfo object\n  return layoutInfo;\n};\n\n\n/**\n * @brief : This function finds the index of the lowest common\n *          graph ancestor between 2 nodes in the subtree\n *          (from the graph hierarchy induced tree) whose\n *          root is graphIx\n *\n * @arg node1: node1's ID\n * @arg node2: node2's ID\n * @arg layoutInfo: layoutInfo object\n *\n */\nvar findLCA = function(node1, node2, layoutInfo) {\n  // Find their common ancester, starting from the root graph\n  var res = findLCA_aux(node1, node2, 0, layoutInfo);\n  if (2 > res.count) {\n    // If aux function couldn't find the common ancester,\n    // then it is the root graph\n    return 0;\n  } else {\n    return res.graph;\n  }\n};\n\n\n/**\n * @brief          : Auxiliary function used for LCA computation\n *\n * @arg node1      : node1's ID\n * @arg node2      : node2's ID\n * @arg graphIx    : subgraph index\n * @arg layoutInfo : layoutInfo object\n *\n * @return         : object of the form {count: X, graph: Y}, where:\n *                   X is the number of ancesters (max: 2) found in\n *                   graphIx (and it's subgraphs),\n *                   Y is the graph index of the lowest graph containing\n *                   all X nodes\n */\nvar findLCA_aux = function(node1, node2, graphIx, layoutInfo) {\n  var graph = layoutInfo.graphSet[graphIx];\n  // If both nodes belongs to graphIx\n  if (-1 < graph.indexOf(node1) && -1 < graph.indexOf(node2)) {\n    return {count:2, graph:graphIx};\n  }\n\n  // Make recursive calls for all subgraphs\n  var c = 0;\n  for (var i = 0; i < graph.length; i++) {\n    var nodeId   = graph[i];\n    var nodeIx   = layoutInfo.idToIndex[nodeId];\n    var children = layoutInfo.layoutNodes[nodeIx].children;\n\n    // If the node has no child, skip it\n    if (0 === children.length) {\n    continue;\n    }\n\n    var childGraphIx = layoutInfo.indexToGraph[layoutInfo.idToIndex[children[0]]];\n    var result = findLCA_aux(node1, node2, childGraphIx, layoutInfo);\n    if (0 === result.count) {\n    // Neither node1 nor node2 are present in this subgraph\n    continue;\n    } else if (1 === result.count) {\n    // One of (node1, node2) is present in this subgraph\n    c++;\n    if (2 === c) {\n      // We've already found both nodes, no need to keep searching\n      break;\n    }\n    } else {\n    // Both nodes are present in this subgraph\n    return result;\n    }\n  }\n\n  return {count:c, graph:graphIx};\n};\n\n\n/**\n * @brief: printsLayoutInfo into js console\n *         Only used for debbuging\n */\nvar printLayoutInfo = function(layoutInfo) {\n  /* jshint ignore:start */\n\n  if (!DEBUG) {\n    return;\n  }\n  console.debug(\"layoutNodes:\");\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = layoutInfo.layoutNodes[i];\n    var s =\n    \"\\nindex: \"     + i +\n    \"\\nId: \"        + n.id +\n    \"\\nChildren: \"  + n.children.toString() +\n    \"\\nparentId: \"  + n.parentId  +\n    \"\\npositionX: \" + n.positionX +\n    \"\\npositionY: \" + n.positionY +\n    \"\\nOffsetX: \" + n.offsetX +\n    \"\\nOffsetY: \" + n.offsetY +\n    \"\\npadLeft: \" + n.padLeft +\n    \"\\npadRight: \" + n.padRight +\n    \"\\npadTop: \" + n.padTop +\n    \"\\npadBottom: \" + n.padBottom;\n\n    console.debug(s);\n  }\n\n  console.debug('idToIndex');\n  for (var i in layoutInfo.idToIndex) {\n    console.debug(\"Id: \" + i + \"\\nIndex: \" + layoutInfo.idToIndex[i]);\n  }\n\n  console.debug('Graph Set');\n  var set = layoutInfo.graphSet;\n  for (var i = 0; i < set.length; i ++) {\n    console.debug(\"Set : \" + i + \": \" + set[i].toString());\n  }\n\n  var s = 'IndexToGraph';\n  for (var i = 0; i < layoutInfo.indexToGraph.length; i ++) {\n    s += \"\\nIndex : \" + i + \" Graph: \"+ layoutInfo.indexToGraph[i];\n  }\n  console.debug(s);\n\n  s = 'Layout Edges';\n  for (var i = 0; i < layoutInfo.layoutEdges.length; i++) {\n    var e = layoutInfo.layoutEdges[i];\n    s += \"\\nEdge Index: \" + i + \" ID: \" + e.id +\n    \" SouceID: \" + e.sourceId + \" TargetId: \" + e.targetId +\n    \" Ideal Length: \" + e.idealLength;\n  }\n  console.debug(s);\n\n  s =  \"nodeSize: \" + layoutInfo.nodeSize;\n  s += \"\\nedgeSize: \" + layoutInfo.edgeSize;\n  s += \"\\ntemperature: \" + layoutInfo.temperature;\n  console.debug(s);\n\n  return;\n  /* jshint ignore:end */\n};\n\n\n/**\n * @brief : Randomizes the position of all nodes\n */\nvar randomizePositions = function(layoutInfo, cy) {\n  var width     = layoutInfo.clientWidth;\n  var height    = layoutInfo.clientHeight;\n\n  for (var i = 0; i < layoutInfo.nodeSize; i++) {\n    var n = layoutInfo.layoutNodes[i];\n\n    // No need to randomize compound nodes or locked nodes\n    if ( 0 === n.children.length && !n.isLocked ) {\n      n.positionX = Math.random() * width;\n      n.positionY = Math.random() * height;\n    }\n  }\n};\n\n\n/**\n * @brief          : Updates the positions of nodes in the network\n * @arg layoutInfo : LayoutInfo object\n * @arg cy         : Cytoscape object\n * @arg options    : Layout options\n */\nvar refreshPositions = function(layoutInfo, cy, options) {\n  // var s = 'Refreshing positions';\n  // logDebug(s);\n\n  var layout = options.layout;\n  var nodes = options.eles.nodes();\n  var bb = layoutInfo.boundingBox;\n  var coseBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity };\n\n  if( options.boundingBox ){\n    nodes.forEach(function( node ){\n      var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]];\n\n      coseBB.x1 = Math.min( coseBB.x1, lnode.positionX );\n      coseBB.x2 = Math.max( coseBB.x2, lnode.positionX );\n\n      coseBB.y1 = Math.min( coseBB.y1, lnode.positionY );\n      coseBB.y2 = Math.max( coseBB.y2, lnode.positionY );\n    });\n\n    coseBB.w = coseBB.x2 - coseBB.x1;\n    coseBB.h = coseBB.y2 - coseBB.y1;\n  }\n\n  nodes.positions(function(i, ele) {\n    var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[ele.data('id')]];\n    // s = \"Node: \" + lnode.id + \". Refreshed position: (\" +\n    // lnode.positionX + \", \" + lnode.positionY + \").\";\n    // logDebug(s);\n\n    if( options.boundingBox ){ // then add extra bounding box constraint\n      var pctX = (lnode.positionX - coseBB.x1) / coseBB.w;\n      var pctY = (lnode.positionY - coseBB.y1) / coseBB.h;\n\n      return {\n        x: bb.x1 + pctX * bb.w,\n        y: bb.y1 + pctY * bb.h\n      };\n    } else {\n      return {\n        x: lnode.positionX,\n        y: lnode.positionY\n      };\n    }\n  });\n\n  // Trigger layoutReady only on first call\n  if (true !== layoutInfo.ready) {\n    // s = 'Triggering layoutready';\n    // logDebug(s);\n    layoutInfo.ready = true;\n    layout.one('layoutready', options.ready);\n    layout.trigger({ type: 'layoutready', layout: this });\n  }\n};\n\n/**\n * @brief : Logs a debug message in JS console, if DEBUG is ON\n */\n// var logDebug = function(text) {\n//   if (DEBUG) {\n//     console.debug(text);\n//   }\n// };\n\nmodule.exports = CoseLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\n\nvar defaults = {\n  fit: true, // whether to fit the viewport to the graph\n  padding: 30, // padding used on fit\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n  avoidOverlapPadding: 10, // extra spacing around nodes when avoidOverlap: true\n  condense: false, // uses all available space on false, uses minimal space on true\n  rows: undefined, // force num of rows in the grid\n  cols: undefined, // force num of columns in the grid\n  position: function( node ){}, // returns { row, col } for element\n  sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction GridLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nGridLayout.prototype.run = function(){\n  var params = this.options;\n  var options = params;\n\n  var cy = params.cy;\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n\n  if( options.sort ){\n    nodes = nodes.sort( options.sort );\n  }\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  if( bb.h === 0 || bb.w === 0){\n    nodes.layoutPositions(this, options, function(){\n      return { x: bb.x1, y: bb.y1 };\n    });\n\n  } else {\n\n    // width/height * splits^2 = cells where splits is number of times to split width\n    var cells = nodes.size();\n    var splits = Math.sqrt( cells * bb.h/bb.w );\n    var rows = Math.round( splits );\n    var cols = Math.round( bb.w/bb.h * splits );\n\n    var small = function(val){\n      if( val == null ){\n        return Math.min(rows, cols);\n      } else {\n        var min = Math.min(rows, cols);\n        if( min == rows ){\n          rows = val;\n        } else {\n          cols = val;\n        }\n      }\n    };\n\n    var large = function(val){\n      if( val == null ){\n        return Math.max(rows, cols);\n      } else {\n        var max = Math.max(rows, cols);\n        if( max == rows ){\n          rows = val;\n        } else {\n          cols = val;\n        }\n      }\n    };\n\n    var oRows = options.rows;\n    var oCols = options.cols != null ? options.cols : options.columns;\n\n    // if rows or columns were set in options, use those values\n    if( oRows != null && oCols != null ){\n      rows = oRows;\n      cols = oCols;\n    } else if( oRows != null && oCols == null ){\n      rows = oRows;\n      cols = Math.ceil( cells / rows );\n    } else if( oRows == null && oCols != null ){\n      cols = oCols;\n      rows = Math.ceil( cells / cols );\n    }\n\n    // otherwise use the automatic values and adjust accordingly\n\n    // if rounding was up, see if we can reduce rows or columns\n    else if( cols * rows > cells ){\n      var sm = small();\n      var lg = large();\n\n      // reducing the small side takes away the most cells, so try it first\n      if( (sm - 1) * lg >= cells ){\n        small(sm - 1);\n      } else if( (lg - 1) * sm >= cells ){\n        large(lg - 1);\n      }\n    } else {\n\n      // if rounding was too low, add rows or columns\n      while( cols * rows < cells ){\n        var sm = small();\n        var lg = large();\n\n        // try to add to larger side first (adds less in multiplication)\n        if( (lg + 1) * sm >= cells ){\n          large(lg + 1);\n        } else {\n          small(sm + 1);\n        }\n      }\n    }\n\n    var cellWidth = bb.w / cols;\n    var cellHeight = bb.h / rows;\n\n    if( options.condense ){\n      cellWidth = 0;\n      cellHeight = 0;\n    }\n\n    if( options.avoidOverlap ){\n      for( var i = 0; i < nodes.length; i++ ){\n        var node = nodes[i];\n        var pos = node._private.position;\n\n        if( pos.x == null || pos.y == null ){ // for bb\n          pos.x = 0;\n          pos.y = 0;\n        }\n\n        var nbb = node.boundingBox();\n        var p = options.avoidOverlapPadding;\n\n        var w = nbb.w + p;\n        var h = nbb.h + p;\n\n        cellWidth = Math.max( cellWidth, w );\n        cellHeight = Math.max( cellHeight, h );\n      }\n    }\n\n    var cellUsed = {}; // e.g. 'c-0-2' => true\n\n    var used = function(row, col){\n      return cellUsed['c-' + row + '-' + col] ? true : false;\n    };\n\n    var use = function(row, col){\n      cellUsed['c-' + row + '-' + col] = true;\n    };\n\n    // to keep track of current cell position\n    var row = 0;\n    var col = 0;\n    var moveToNextCell = function(){\n      col++;\n      if( col >= cols ){\n        col = 0;\n        row++;\n      }\n    };\n\n    // get a cache of all the manual positions\n    var id2manPos = {};\n    for( var i = 0; i < nodes.length; i++ ){\n      var node = nodes[i];\n      var rcPos = options.position( node );\n\n      if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd\n        var pos = {\n          row: rcPos.row,\n          col: rcPos.col\n        };\n\n        if( pos.col === undefined ){ // find unused col\n          pos.col = 0;\n\n          while( used(pos.row, pos.col) ){\n            pos.col++;\n          }\n        } else if( pos.row === undefined ){ // find unused row\n          pos.row = 0;\n\n          while( used(pos.row, pos.col) ){\n            pos.row++;\n          }\n        }\n\n        id2manPos[ node.id() ] = pos;\n        use( pos.row, pos.col );\n      }\n    }\n\n    var getPos = function(i, element){\n      var x, y;\n\n      if( element.locked() || element.isFullAutoParent() ){\n        return false;\n      }\n\n      // see if we have a manual position set\n      var rcPos = id2manPos[ element.id() ];\n      if( rcPos ){\n        x = rcPos.col * cellWidth + cellWidth/2 + bb.x1;\n        y = rcPos.row * cellHeight + cellHeight/2 + bb.y1;\n\n      } else { // otherwise set automatically\n\n        while( used(row, col) ){\n          moveToNextCell();\n        }\n\n        x = col * cellWidth + cellWidth/2 + bb.x1;\n        y = row * cellHeight + cellHeight/2 + bb.y1;\n        use( row, col );\n\n        moveToNextCell();\n      }\n\n      return { x: x, y: y };\n\n    };\n\n    nodes.layoutPositions( this, options, getPos );\n  }\n\n  return this; // chaining\n\n};\n\nmodule.exports = GridLayout;\n","'use strict';\n\nmodule.exports = [\n  { name: 'breadthfirst', impl: require('./breadthfirst') },\n  { name: 'circle', impl: require('./circle') },\n  { name: 'concentric',impl: require('./concentric') },\n  { name: 'cose', impl: require('./cose') },\n  { name: 'grid', impl: require('./grid') },\n  { name: 'null', impl: require('./null') },\n  { name: 'preset', impl: require('./preset') },\n  { name: 'random', impl: require('./random') }\n];\n","'use strict';\n\nvar util = require('../../util');\n\n// default layout options\nvar defaults = {\n  ready: function(){}, // on layoutready\n  stop: function(){} // on layoutstop\n};\n\n// constructor\n// options : object containing layout options\nfunction NullLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\n// runs the layout\nNullLayout.prototype.run = function(){\n  var options = this.options;\n  var eles = options.eles; // elements to consider in the layout\n  var layout = this;\n\n  // cy is automatically populated for us in the constructor\n  var cy = options.cy; // jshint ignore:line\n\n  layout.trigger('layoutstart');\n\n  // puts all nodes at (0, 0)\n  eles.nodes().positions(function(){\n    return {\n      x: 0,\n      y: 0\n    };\n  });\n\n  // trigger layoutready when each node has had its position set at least once\n  layout.one('layoutready', options.ready);\n  layout.trigger('layoutready');\n\n  // trigger layoutstop when the layout stops (e.g. finishes)\n  layout.one('layoutstop', options.stop);\n  layout.trigger('layoutstop');\n\n  return this; // chaining\n};\n\n// called on continuous layouts to stop them before they finish\nNullLayout.prototype.stop = function(){\n  return this; // chaining\n};\n\nmodule.exports = NullLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar is = require('../../is');\n\nvar defaults = {\n  positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; }\n  zoom: undefined, // the zoom level to set (prob want fit = false if set)\n  pan: undefined, // the pan level to set (prob want fit = false if set)\n  fit: true, // whether to fit to viewport\n  padding: 30, // padding on fit\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction PresetLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nPresetLayout.prototype.run = function(){\n  var options = this.options;\n  var eles = options.eles;\n\n  var nodes = eles.nodes();\n  var posIsFn = is.fn( options.positions );\n\n  function getPosition(node){\n    if( options.positions == null ){\n      return null;\n    }\n\n    if( posIsFn ){\n      return options.positions.apply( node, [ node ] );\n    }\n\n    var pos = options.positions[node._private.data.id];\n\n    if( pos == null ){\n      return null;\n    }\n\n    return pos;\n  }\n\n  nodes.layoutPositions(this, options, function(i, node){\n    var position = getPosition(node);\n\n    if( node.locked() || position == null ){\n      return false;\n    }\n\n    return position;\n  });\n\n  return this; // chaining\n};\n\nmodule.exports = PresetLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\n\nvar defaults = {\n  fit: true, // whether to fit to viewport\n  padding: 30, // fit padding\n  boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n  animate: false, // whether to transition the node positions\n  animationDuration: 500, // duration of animation in ms if enabled\n  animationEasing: undefined, // easing of animation if enabled\n  ready: undefined, // callback on layoutready\n  stop: undefined // callback on layoutstop\n};\n\nfunction RandomLayout( options ){\n  this.options = util.extend({}, defaults, options);\n}\n\nRandomLayout.prototype.run = function(){\n  var options = this.options;\n  var cy = options.cy;\n  var eles = options.eles;\n  var nodes = eles.nodes().not(':parent');\n\n  var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n    x1: 0, y1: 0, w: cy.width(), h: cy.height()\n  } );\n\n  var getPos = function( i, node ){\n    return {\n      x: bb.x1 + Math.round( Math.random() * bb.w ),\n      y: bb.y1 + Math.round( Math.random() * bb.h )\n    };\n  };\n\n  nodes.layoutPositions( this, options, getPos );\n\n  return this; // chaining\n};\n\nmodule.exports = RandomLayout;\n","'use strict';\n\nvar math = require('../../../math');\nvar is = require('../../../is');\nvar util = require('../../../util');\n\nvar BRp = {};\n\nBRp.arrowShapeHeight = 0.3;\n\nBRp.registerArrowShapes = function(){\n  var arrowShapes = this.arrowShapes = {};\n  var renderer = this;\n\n  // Contract for arrow shapes:\n  // 0, 0 is arrow tip\n  // (0, 1) is direction towards node\n  // (1, 0) is right\n  //\n  // functional api:\n  // collide: check x, y in shape\n  // roughCollide: called before collide, no false negatives\n  // draw: draw\n  // spacing: dist(arrowTip, nodeBoundary)\n  // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip\n\n  var bbCollide = function( x, y, size, angle, translation, padding ){\n    var x1 = translation.x - size/2 - padding;\n    var x2 = translation.x + size/2 + padding;\n    var y1 = translation.y - size/2 - padding;\n    var y2 = translation.y + size/2 + padding;\n\n    var inside = (x1 <= x && x <= x2) && (y1 <= y && y <= y2);\n\n    return inside;\n  };\n\n  var transform = function( x, y, size, angle, translation ){\n    var xRotated = x * Math.cos(angle) - y * Math.sin(angle);\n    var yRotated = x * Math.sin(angle) + y * Math.cos(angle);\n\n    var xScaled = xRotated * size;\n    var yScaled = yRotated * size;\n\n    var xTranslated = xScaled + translation.x;\n    var yTranslated = yScaled + translation.y;\n\n    return {\n      x: xTranslated,\n      y: yTranslated\n    };\n  };\n\n  var transformPoints = function( pts, size, angle, translation ){\n    var retPts = [];\n\n    for( var i = 0; i < pts.length; i += 2 ){\n      var x = pts[i];\n      var y = pts[i + 1];\n\n      retPts.push( transform(x, y, size, angle, translation) );\n    }\n\n    return retPts;\n  };\n\n  var pointsToArr = function( pts ){\n    var ret = [];\n\n    for( var i = 0; i < pts.length; i++ ){\n      var p = pts[i];\n\n      ret.push( p.x, p.y );\n    }\n\n    return ret;\n  };\n\n  var defineArrowShape = function( name, defn ){\n    if( is.string(defn) ){\n      defn = arrowShapes[ defn ];\n    }\n\n    arrowShapes[ name ] = util.extend( {\n      name: name,\n\n      points: [\n        -0.15, -0.3,\n        0.15, -0.3,\n        0.15, 0.3,\n        -0.15, 0.3\n      ],\n\n      collide: function( x, y, size, angle, translation, padding ){\n        var points = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );\n        var inside = math.pointInsidePolygonPoints( x, y, points );\n\n        return inside;\n      },\n\n      roughCollide: bbCollide,\n\n      draw: function( context, size, angle, translation ){\n        var points = transformPoints( this.points, size, angle, translation );\n\n        renderer.arrowShapeImpl('polygon')( context, points );\n      },\n\n      spacing: function( edge ){\n        return 0;\n      },\n\n      gap: function( edge ){\n        return edge._private.style['width'].pfValue * 2;\n      }\n    }, defn );\n  };\n\n  defineArrowShape( 'none', {\n    collide: util.falsify,\n\n    roughCollide: util.falsify,\n\n    draw: util.noop,\n\n    spacing: util.zeroify,\n\n    gap: util.zeroify\n  } );\n\n  defineArrowShape( 'triangle', {\n    points: [\n      -0.15, -0.3,\n      0, 0,\n      0.15, -0.3\n    ]\n  } );\n\n  defineArrowShape( 'arrow', 'triangle' );\n\n  defineArrowShape( 'triangle-backcurve', {\n    points: arrowShapes['triangle'].points,\n\n    controlPoint: [ 0, -0.15 ],\n\n    roughCollide: bbCollide,\n\n    draw: function( context, size, angle, translation ){\n      var ptsTrans = transformPoints( this.points, size, angle, translation );\n      var ctrlPt = this.controlPoint;\n      var ctrlPtTrans = transform( ctrlPt[0], ctrlPt[1], size, angle, translation );\n\n      renderer.arrowShapeImpl( this.name )( context, ptsTrans, ctrlPtTrans );\n    },\n\n    gap: function( edge ){\n      return edge._private.style['width'].pfValue;\n    }\n  } );\n\n\n  defineArrowShape( 'triangle-tee', {\n    points: [\n      -0.15, -0.3,\n      0, 0,\n      0.15, -0.3,\n      -0.15, -0.3\n    ],\n\n    pointsTee: [\n      -0.15, -0.4,\n      -0.15, -0.5,\n      0.15, -0.5,\n      0.15, -0.4\n    ],\n\n    collide: function( x, y, size, angle, translation, padding ){\n      var triPts = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );\n      var teePts = pointsToArr( transformPoints( this.pointsTee, size + 2*padding, angle, translation ) );\n\n      var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts );\n\n      return inside;\n    },\n\n    draw: function( context, size, angle, translation ){\n      var triPts = transformPoints( this.points, size, angle, translation );\n      var teePts = transformPoints( this.pointsTee, size, angle, translation );\n\n      renderer.arrowShapeImpl( this.name )( context, triPts, teePts );\n    }\n  } );\n\n  defineArrowShape( 'vee', {\n    points: [\n      -0.15, -0.3,\n      0, 0,\n      0.15, -0.3,\n      0, -0.15\n    ],\n\n    gap: function( edge ){\n      return edge._private.style['width'].pfValue;\n    }\n  } );\n\n  defineArrowShape( 'half-triangle-overshot', {\n    points: [\n      0, -0.25,\n      -0.5, -0.25,\n      0.5, 0.25\n    ],\n\n    leavePathOpen: true,\n\n    matchEdgeWidth: true\n  } );\n\n  defineArrowShape( 'circle', {\n    radius: 0.15,\n\n    collide: function( x, y, size, angle, translation, padding ){\n      var t = translation;\n      var inside = ( Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2*padding) * this.radius, 2) );\n\n      return inside;\n    },\n\n    draw: function( context, size, angle, translation ){\n      renderer.arrowShapeImpl( this.name )( context, translation.x, translation.y, this.radius * size );\n    },\n\n    spacing: function( edge ){\n      return renderer.getArrowWidth(edge._private.style['width'].pfValue)\n        * this.radius;\n    }\n  } );\n\n  defineArrowShape( 'inhibitor', {\n    points: [\n      -0.25, 0,\n      -0.25, -0.1,\n      0.25, -0.1,\n      0.25, 0\n    ],\n\n    spacing: function( edge ){\n      return 1;\n    },\n\n    gap: function( edge ){\n      return 1;\n    }\n  } );\n\n  defineArrowShape( 'tee', 'inhibitor' );\n\n  defineArrowShape( 'square', {\n    points: [\n      -0.15, 0.00,\n      0.15, 0.00,\n      0.15, -0.3,\n      -0.15, -0.3\n    ]\n  } );\n\n  defineArrowShape( 'diamond', {\n    points: [\n      -0.15, -0.15,\n      0, -0.3,\n      0.15, -0.15,\n      0, 0\n    ],\n\n    gap: function( edge ){\n      return edge._private.style['width'].pfValue;\n    }\n  } );\n\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar BRp = {};\n\nvar delEleCache = function( r ){\n  r.eleEache = null;\n};\n\nvar getEleCache = function( r ){\n  if( !r.eleEache ){\n    r.eleEache = {\n      nodes: r.cy.nodes(),\n      edges: r.cy.edges()\n    };\n  }\n\n  return r.eleEache;\n};\n\nBRp.getCachedElements = function(){\n  return getEleCache( this );\n};\n\nBRp.getCachedNodes = function(){\n  return getEleCache( this ).nodes;\n};\n\nBRp.getCachedEdges = function(){\n  return getEleCache( this ).edges;\n};\n\nBRp.updateElementsCache = function(){\n  var r = this;\n\n  delEleCache( r );\n\n  return getEleCache( r );\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar math = require('../../../math');\nvar is = require('../../../is');\nvar zIndexSort = require('../../../collection/zsort');\n\nvar BRp = {};\n\n// Project mouse\nBRp.projectIntoViewport = function(clientX, clientY) {\n  var offsets = this.findContainerClientCoords();\n  var offsetLeft = offsets[0];\n  var offsetTop = offsets[1];\n\n  var x = clientX - offsetLeft;\n  var y = clientY - offsetTop;\n\n  x -= this.cy.pan().x; y -= this.cy.pan().y; x /= this.cy.zoom(); y /= this.cy.zoom();\n  return [x, y];\n};\n\nBRp.findContainerClientCoords = function() {\n  var container = this.container;\n\n  var bb = this.containerBB = this.containerBB || container.getBoundingClientRect();\n\n  return [bb.left, bb.top, bb.right - bb.left, bb.bottom - bb.top];\n};\n\nBRp.invalidateContainerClientCoordsCache = function(){\n  this.containerBB = null;\n};\n\n// Find nearest element\nBRp.findNearestElement = function(x, y, visibleElementsOnly, isTouch){\n  var self = this;\n  var r = this;\n  var eles = r.getCachedZSortedEles();\n  var near = [];\n  var zoom = r.cy.zoom();\n  var hasCompounds = r.cy.hasCompoundNodes();\n  var edgeThreshold = (isTouch ? 24 : 8) / zoom;\n  var nodeThreshold = (isTouch ? 8 : 2) / zoom;\n  var labelThreshold = (isTouch ? 8 : 2) / zoom;\n\n  function checkNode(node){\n    var _p = node._private;\n\n    if( _p.style['events'].strValue === 'no' ){ return; }\n\n    var width = node.outerWidth() + 2*nodeThreshold;\n    var height = node.outerHeight() + 2*nodeThreshold;\n    var hw = width/2;\n    var hh = height/2;\n    var pos = _p.position;\n\n    if(\n      pos.x - hw <= x && x <= pos.x + hw // bb check x\n        &&\n      pos.y - hh <= y && y <= pos.y + hh // bb check y\n    ){\n      var visible = !visibleElementsOnly || ( node.visible() && !node.transparent() );\n\n      // exit early if invisible edge and must be visible\n      if( visibleElementsOnly && !visible ){\n        return;\n      }\n\n      var shape = r.nodeShapes[ self.getNodeShape(node) ];\n\n      if(\n        shape.checkPoint(x, y, 0, width, height, pos.x, pos.y)\n      ){\n        near.push( node );\n      }\n\n    }\n  }\n\n  function checkEdge(edge){\n    var _p = edge._private;\n\n    if( _p.style['events'].strValue === 'no' ){ return; }\n\n    var rs = _p.rscratch;\n    var style = _p.style;\n    var width = style['width'].pfValue/2 + edgeThreshold; // more like a distance radius from centre\n    var widthSq = width * width;\n    var width2 = width * 2;\n    var src = _p.source;\n    var tgt = _p.target;\n    var inEdgeBB = false;\n    var sqDist;\n\n    // exit early if invisible edge and must be visible\n    var passedVisibilityCheck;\n    var passesVisibilityCheck = function(){\n      if( passedVisibilityCheck !== undefined ){\n        return passedVisibilityCheck;\n      }\n\n      if( !visibleElementsOnly ){\n        passedVisibilityCheck = true;\n        return true;\n      }\n\n      var visible = edge.visible() && !edge.transparent();\n      if( visible ){\n        passedVisibilityCheck = true;\n        return true;\n      }\n\n      passedVisibilityCheck = false;\n      return false;\n    };\n\n    if( rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack' ){\n      var pts = rs.allpts;\n\n      for( var i = 0; i + 3 < pts.length; i += 2 ){\n        if(\n          (inEdgeBB = math.inLineVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], width2))\n            && passesVisibilityCheck() &&\n          widthSq > ( sqDist = math.sqDistanceToFiniteLine(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3]) )\n        ){\n          near.push( edge );\n        }\n      }\n\n    } else if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n      var pts = rs.allpts;\n      for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){\n        if(\n          (inEdgeBB = math.inBezierVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5], width2))\n            && passesVisibilityCheck() &&\n          (widthSq > (sqDist = math.sqDistanceToQuadraticBezier(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5])) )\n        ){\n          near.push( edge );\n        }\n      }\n    }\n\n    // if we're close to the edge but didn't hit it, maybe we hit its arrows\n    if( inEdgeBB && passesVisibilityCheck() && near.length === 0 || near[near.length - 1] !== edge ){\n      var src = src || _p.source;\n      var tgt = tgt || _p.target;\n\n      var eWidth = style['width'].pfValue;\n      var arSize = self.getArrowWidth( eWidth );\n\n      var arrows = [\n        { name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle },\n        { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle },\n        { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle },\n        { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle }\n      ];\n\n      for( var i = 0; i < arrows.length; i++ ){\n        var ar = arrows[i];\n        var shape = r.arrowShapes[ style[ar.name+'-arrow-shape'].value ];\n\n        if(\n          shape.roughCollide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)\n           &&\n          shape.collide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)\n        ){\n          near.push( edge );\n          break;\n        }\n      }\n    }\n\n    // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence)\n    if( hasCompounds &&  near.length > 0 && near[ near.length - 1 ] === edge ){\n      checkNode( src );\n      checkNode( tgt );\n    }\n  }\n\n  function checkLabel(ele){\n    var _p = ele._private;\n    var th = labelThreshold;\n\n    if( _p.style['text-events'].strValue === 'no' ){ return; }\n\n    // adjust bb w/ angle\n    if( _p.group === 'edges' && _p.style['edge-text-rotation'].strValue === 'autorotate' ){\n\n      var rstyle = _p.rstyle;\n      var lw = rstyle.labelWidth + 2*th;\n      var lh = rstyle.labelHeight + 2*th;\n      var lx = rstyle.labelX;\n      var ly = rstyle.labelY;\n\n      var theta = _p.rscratch.labelAngle;\n      var cos = Math.cos( theta );\n      var sin = Math.sin( theta );\n\n      var rotate = function( x, y ){\n        x = x - lx;\n        y = y - ly;\n\n        return {\n          x: x*cos - y*sin + lx,\n          y: x*sin + y*cos + ly\n        };\n      };\n\n      var lx1 = lx - lw/2;\n      var lx2 = lx + lw/2;\n      var ly1 = ly - lh/2;\n      var ly2 = ly + lh/2;\n\n      var px1y1 = rotate( lx1, ly1 );\n      var px1y2 = rotate( lx1, ly2 );\n      var px2y1 = rotate( lx2, ly1 );\n      var px2y2 = rotate( lx2, ly2 );\n\n      var points = [\n        px1y1.x, px1y1.y,\n        px2y1.x, px2y1.y,\n        px2y2.x, px2y2.y,\n        px1y2.x, px1y2.y\n      ];\n\n      if( math.pointInsidePolygonPoints( x, y, points ) ){\n        near.push( ele );\n      }\n\n    } else {\n      var bb = ele.boundingBox({\n        includeLabels: true,\n        includeNodes: false,\n        includeEdges: false\n      });\n\n      // adjust bb w/ threshold\n      bb.x1 -= th;\n      bb.y1 -= th;\n      bb.x2 += th;\n      bb.y2 += th;\n      bb.w = bb.x2 - bb.x1;\n      bb.h = bb.y2 - bb.y1;\n\n      if( math.inBoundingBox( bb, x, y ) ){\n        near.push( ele );\n      }\n    }\n\n  }\n\n  for( var i = eles.length - 1; i >= 0; i-- ){ // reverse order for precedence\n    var ele = eles[i];\n    var _p = ele._private;\n\n    if( near.length > 0 ){ break; } // since we check in z-order, first found is top and best result => exit early\n\n    if( _p.group === 'nodes' ){\n      checkNode( ele );\n\n    } else  { // then edge\n      checkEdge( ele );\n    }\n\n    checkLabel( ele );\n\n  }\n\n\n  if( near.length > 0 ){\n    return near[ near.length - 1 ];\n  } else {\n    return null;\n  }\n};\n\n// 'Give me everything from this box'\nBRp.getAllInBox = function(x1, y1, x2, y2) {\n  var nodes = this.getCachedNodes();\n  var edges = this.getCachedEdges();\n  var box = [];\n\n  var x1c = Math.min(x1, x2);\n  var x2c = Math.max(x1, x2);\n  var y1c = Math.min(y1, y2);\n  var y2c = Math.max(y1, y2);\n\n  x1 = x1c;\n  x2 = x2c;\n  y1 = y1c;\n  y2 = y2c;\n\n  var boxBb = math.makeBoundingBox({\n    x1: x1, y1: y1,\n    x2: x2, y2: y2\n  });\n\n  for ( var i = 0; i < nodes.length; i++ ){\n    var node = nodes[i];\n    var nodeBb = node.boundingBox({\n      includeNodes: true,\n      includeEdges: false,\n      includeLabels: false\n    });\n\n    if( math.boundingBoxesIntersect(boxBb, nodeBb) ){\n      box.push(nodes[i]);\n    }\n  }\n\n  for( var e = 0; e < edges.length; e++ ){\n    var edge = edges[e];\n    var _p = edge._private;\n    var rs = _p.rscratch;\n\n    if( rs.startX != null && rs.startY != null && !math.inBoundingBox( boxBb, rs.startX, rs.startY ) ){ continue; }\n    if( rs.endX != null && rs.endY != null && !math.inBoundingBox( boxBb, rs.endX, rs.endY ) ){ continue; }\n\n    if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack' ){\n\n      var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts;\n      var allInside = true;\n\n      for( var i = 0; i < pts.length; i++ ){\n        if( !math.pointInBoundingBox( boxBb, pts[i] ) ){\n          allInside = false;\n          break;\n        }\n      }\n\n      if( allInside ){\n        box.push( edge );\n      }\n\n    } else if( rs.edgeType === 'haystack' || rs.edgeType === 'straight' ){\n      box.push( edge );\n    }\n\n  }\n\n  return box;\n};\n\n\n/**\n * Returns the shape of the given node. If the height or width of the given node\n * is set to auto, the node is considered to be a compound.\n *\n * @param node          a node\n * @return {String}     shape of the node\n */\nBRp.getNodeShape = function( node ){\n  var r = this;\n  var style = node._private.style;\n  var shape = style['shape'].value;\n\n  if( node.isParent() ){\n    if( shape === 'rectangle' || shape === 'roundrectangle' ){\n      return shape;\n    } else {\n      return 'rectangle';\n    }\n  }\n\n  if( shape === 'polygon' ){\n    var points = style['shape-polygon-points'].value;\n\n    return r.nodeShapes.makePolygon( points ).name;\n  }\n\n  return shape;\n};\n\nBRp.updateCachedZSortedEles = function(){\n  this.getCachedZSortedEles( true );\n};\n\nBRp.getCachedZSortedEles = function( forceRecalc ){\n  var lastNodes = this.lastZOrderCachedNodes;\n  var lastEdges = this.lastZOrderCachedEdges;\n  var nodes = this.getCachedNodes();\n  var edges = this.getCachedEdges();\n  var eles = [];\n\n  if( forceRecalc || !lastNodes || !lastEdges || lastNodes !== nodes || lastEdges !== edges ){\n    //console.time('cachezorder')\n\n    for( var i = 0; i < nodes.length; i++ ){\n      var n = nodes[i];\n\n      if( n.animated() || (n.visible() && !n.transparent()) ){\n        eles.push( n );\n      }\n    }\n\n    for( var i = 0; i < edges.length; i++ ){\n      var e = edges[i];\n\n      if( e.animated() || (e.visible() && !e.transparent()) ){\n        eles.push( e );\n      }\n    }\n\n    eles.sort( zIndexSort );\n    this.cachedZSortedEles = eles;\n    //console.log('make cache')\n\n    //console.timeEnd('cachezorder')\n  } else {\n    eles = this.cachedZSortedEles;\n    //console.log('read cache')\n  }\n\n  this.lastZOrderCachedNodes = nodes;\n  this.lastZOrderCachedEdges = edges;\n\n  return eles;\n};\n\nfunction pushBezierPts(edge, pts){\n  var qbezierAt = function( p1, p2, p3, t ){ return math.qbezierAt(p1, p2, p3, t); };\n  var _p = edge._private;\n  var bpts = _p.rstyle.bezierPts;\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.05 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.05 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.25 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.25 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.4 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.4 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.5 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.5 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.6 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.6 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.75 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.75 )\n  });\n\n  bpts.push({\n    x: qbezierAt( pts[0], pts[2], pts[4], 0.95 ),\n    y: qbezierAt( pts[1], pts[3], pts[5], 0.95 )\n  });\n}\n\nBRp.projectLines = function( edge ){\n  var _p = edge._private;\n  var rs = _p.rscratch;\n  var et = rs.edgeType;\n\n  if( et === 'multibezier' ||  et === 'bezier' ||  et === 'self' ||  et === 'compound' ){\n    var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line\n\n    for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){\n      pushBezierPts( edge, rs.allpts.slice(i, i+6) );\n    }\n  } else if(  et === 'segments' ){\n    var lpts = _p.rstyle.linePts = [];\n\n    for( var i = 0; i + 1 < rs.allpts.length; i += 2 ){\n      lpts.push({\n        x: rs.allpts[i],\n        y: rs.allpts[i+1]\n      });\n    }\n  } else if( et === 'haystack' ){\n    var hpts = rs.haystackPts;\n\n    _p.rstyle.haystackPts = [\n      { x: hpts[0], y: hpts[1] },\n      { x: hpts[2], y: hpts[3] }\n    ];\n  }\n};\n\nBRp.projectBezier = BRp.projectLines;\n\nBRp.recalculateNodeLabelProjection = function( node ){\n  var content = node._private.style['label'].strValue;\n  if( !content || content.match(/^\\s+$/) ){ return; }\n\n  var textX, textY;\n  var nodeWidth = node.outerWidth();\n  var nodeHeight = node.outerHeight();\n  var nodePos = node._private.position;\n  var textHalign = node._private.style['text-halign'].strValue;\n  var textValign = node._private.style['text-valign'].strValue;\n  var rs = node._private.rscratch;\n  var rstyle = node._private.rstyle;\n\n  switch( textHalign ){\n    case 'left':\n      textX = nodePos.x - nodeWidth / 2;\n      break;\n\n    case 'right':\n      textX = nodePos.x + nodeWidth / 2;\n      break;\n\n    default: // e.g. center\n      textX = nodePos.x;\n  }\n\n  switch( textValign ){\n    case 'top':\n      textY = nodePos.y - nodeHeight / 2;\n      break;\n\n    case 'bottom':\n      textY = nodePos.y + nodeHeight / 2;\n      break;\n\n    default: // e.g. middle\n      textY = nodePos.y;\n  }\n\n  rs.labelX = textX;\n  rs.labelY = textY;\n  rstyle.labelX = textX;\n  rstyle.labelY = textY;\n\n  this.applyLabelDimensions( node );\n};\n\nBRp.recalculateEdgeLabelProjection = function( edge ){\n  var content = edge._private.style['label'].strValue;\n  if( !content || content.match(/^\\s+$/) ){ return; }\n\n  var textX, textY;\n  var _p = edge._private;\n  var rs = _p.rscratch;\n  //var style = _p.style;\n  var rstyle = _p.rstyle;\n\n  textX = rs.midX;\n  textY = rs.midY;\n\n  // add center point to style so bounding box calculations can use it\n  rs.labelX = textX;\n  rs.labelY = textY;\n  rstyle.labelX = textX;\n  rstyle.labelY = textY;\n\n  this.applyLabelDimensions( edge );\n};\n\nBRp.applyLabelDimensions = function( ele ){\n  var rs = ele._private.rscratch;\n  var rstyle = ele._private.rstyle;\n\n  var text = this.getLabelText( ele );\n  var labelDims = this.calculateLabelDimensions( ele, text );\n\n  rstyle.labelWidth = labelDims.width;\n  rs.labelWidth = labelDims.width;\n\n  rstyle.labelHeight = labelDims.height;\n  rs.labelHeight = labelDims.height;\n};\n\nBRp.getLabelText = function( ele ){\n  var style = ele._private.style;\n  var text = ele._private.style['label'].strValue;\n  var textTransform = style['text-transform'].value;\n  var rscratch = ele._private.rscratch;\n\n  if (textTransform == 'none') {\n  } else if (textTransform == 'uppercase') {\n    text = text.toUpperCase();\n  } else if (textTransform == 'lowercase') {\n    text = text.toLowerCase();\n  }\n\n  if( style['text-wrap'].value === 'wrap' ){\n    //console.log('wrap');\n\n    // save recalc if the label is the same as before\n    if( rscratch.labelWrapKey === rscratch.labelKey ){\n      // console.log('wrap cache hit');\n      return rscratch.labelWrapCachedText;\n    }\n    // console.log('wrap cache miss');\n\n    var lines = text.split('\\n');\n    var maxW = style['text-max-width'].pfValue;\n    var wrappedLines = [];\n\n    for( var l = 0; l < lines.length; l++ ){\n      var line = lines[l];\n      var lineDims = this.calculateLabelDimensions( ele, line, 'line=' + line );\n      var lineW = lineDims.width;\n\n      if( lineW > maxW ){ // line is too long\n        var words = line.split(/\\s+/); // NB: assume collapsed whitespace into single space\n        var subline = '';\n\n        for( var w = 0; w < words.length; w++ ){\n          var word = words[w];\n          var testLine = subline.length === 0 ? word : subline + ' ' + word;\n          var testDims = this.calculateLabelDimensions( ele, testLine, 'testLine=' + testLine );\n          var testW = testDims.width;\n\n          if( testW <= maxW ){ // word fits on current line\n            subline += word + ' ';\n          } else { // word starts new line\n            wrappedLines.push( subline );\n            subline = word + ' ';\n          }\n        }\n\n        // if there's remaining text, put it in a wrapped line\n        if( !subline.match(/^\\s+$/) ){\n          wrappedLines.push( subline );\n        }\n      } else { // line is already short enough\n        wrappedLines.push( line );\n      }\n    } // for\n\n    rscratch.labelWrapCachedLines = wrappedLines;\n    rscratch.labelWrapCachedText = text = wrappedLines.join('\\n');\n    rscratch.labelWrapKey = rscratch.labelKey;\n\n    // console.log(text)\n  } // if wrap\n\n  return text;\n};\n\nBRp.calculateLabelDimensions = function( ele, text, extraKey ){\n  var r = this;\n  var style = ele._private.style;\n  var fStyle = style['font-style'].strValue;\n  var size = style['font-size'].pfValue + 'px';\n  var family = style['font-family'].strValue;\n  // var variant = style['font-variant'].strValue;\n  var weight = style['font-weight'].strValue;\n\n  var cacheKey = ele._private.labelKey;\n\n  if( extraKey ){\n    cacheKey += '$@$' + extraKey;\n  }\n\n  var cache = r.labelDimCache || (r.labelDimCache = {});\n\n  if( cache[cacheKey] ){\n    return cache[cacheKey];\n  }\n\n  var div = this.labelCalcDiv;\n\n  if( !div ){\n    div = this.labelCalcDiv = document.createElement('div');\n    document.body.appendChild( div );\n  }\n\n  var ds = div.style;\n\n  // from ele style\n  ds.fontFamily = family;\n  ds.fontStyle = fStyle;\n  ds.fontSize = size;\n  // ds.fontVariant = variant;\n  ds.fontWeight = weight;\n\n  // forced style\n  ds.position = 'absolute';\n  ds.left = '-9999px';\n  ds.top = '-9999px';\n  ds.zIndex = '-1';\n  ds.visibility = 'hidden';\n  ds.pointerEvents = 'none';\n  ds.padding = '0';\n  ds.lineHeight = '1';\n\n  if( style['text-wrap'].value === 'wrap' ){\n    ds.whiteSpace = 'pre'; // so newlines are taken into account\n  } else {\n    ds.whiteSpace = 'normal';\n  }\n\n  // put label content in div\n  div.textContent = text;\n\n  cache[cacheKey] = {\n    width: div.clientWidth,\n    height: div.clientHeight\n  };\n\n  return cache[cacheKey];\n};\n\nBRp.recalculateRenderedStyle = function( eles ){\n  var edges = [];\n  var nodes = [];\n  var handledEdge = {};\n\n  for( var i = 0; i < eles.length; i++ ){\n    var ele = eles[i];\n    var _p = ele._private;\n    var style = _p.style;\n    var rs = _p.rscratch;\n    var rstyle = _p.rstyle;\n    var id = _p.data.id;\n    var bbStyleSame = rs.boundingBoxKey != null && _p.boundingBoxKey === rs.boundingBoxKey;\n    var labelStyleSame = rs.labelKey != null && _p.labelKey === rs.labelKey;\n    var styleSame = bbStyleSame && labelStyleSame;\n\n    if( _p.group === 'nodes' ){\n      var pos = _p.position;\n      var posSame = rstyle.nodeX != null && rstyle.nodeY != null && pos.x === rstyle.nodeX && pos.y === rstyle.nodeY;\n      var wSame = rstyle.nodeW != null && rstyle.nodeW === style['width'].pfValue;\n      var hSame = rstyle.nodeH != null && rstyle.nodeH === style['height'].pfValue;\n\n      if( !posSame || !styleSame || !wSame || !hSame ){\n        nodes.push( ele );\n      }\n\n      rstyle.nodeX = pos.x;\n      rstyle.nodeY = pos.y;\n      rstyle.nodeW = style['width'].pfValue;\n      rstyle.nodeH = style['height'].pfValue;\n    } else { // edges\n\n      var srcPos = _p.source._private.position;\n      var tgtPos = _p.target._private.position;\n      var srcSame = rstyle.srcX != null && rstyle.srcY != null && srcPos.x === rstyle.srcX && srcPos.y === rstyle.srcY;\n      var tgtSame = rstyle.tgtX != null && rstyle.tgtY != null && tgtPos.x === rstyle.tgtX && tgtPos.y === rstyle.tgtY;\n      var positionsSame = srcSame && tgtSame;\n\n      if( !positionsSame || !styleSame ){\n        if( rs.edgeType === 'bezier' || rs.edgeType === 'straight' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n          if( !handledEdge[ id ] ){\n            edges.push( ele );\n            handledEdge[ id ] = true;\n\n            var parallelEdges = ele.parallelEdges();\n            for( var i = 0; i < parallelEdges.length; i++ ){\n              var pEdge = parallelEdges[i];\n              var pId = pEdge._private.data.id;\n\n              if( !handledEdge[ pId ] ){\n                edges.push( pEdge );\n                handledEdge[ pId ] = true;\n              }\n\n            }\n          }\n        } else {\n          edges.push( ele );\n        }\n      } // if positions diff\n\n      // update rstyle positions\n      rstyle.srcX = srcPos.x;\n      rstyle.srcY = srcPos.y;\n      rstyle.tgtX = tgtPos.x;\n      rstyle.tgtY = tgtPos.y;\n\n    } // if edges\n\n    rs.boundingBoxKey = _p.boundingBoxKey;\n    rs.labelKey = _p.labelKey;\n  }\n\n  this.recalculateEdgeProjections( edges );\n  this.recalculateLabelProjections( nodes, edges );\n};\n\nBRp.recalculateLabelProjections = function( nodes, edges ){\n  for( var i = 0; i < nodes.length; i++ ){\n    this.recalculateNodeLabelProjection( nodes[i] );\n  }\n\n  for( var i = 0; i < edges.length; i++ ){\n    this.recalculateEdgeLabelProjection( edges[i] );\n  }\n};\n\nBRp.recalculateEdgeProjections = function( edges ){\n  this.findEdgeControlPoints( edges );\n};\n\n\n// Find edge control points\nBRp.findEdgeControlPoints = function(edges) {\n  if( !edges || edges.length === 0 ){ return; }\n\n  var r = this;\n  var cy = r.cy;\n  var hasCompounds = cy.hasCompoundNodes();\n  var hashTable = {};\n  var pairIds = [];\n  var haystackEdges = [];\n  var autorotateEdges = [];\n\n  // create a table of edge (src, tgt) => list of edges between them\n  var pairId;\n  for (var i = 0; i < edges.length; i++){\n    var edge = edges[i];\n    var _p = edge._private;\n    var data = _p.data;\n    var style = _p.style;\n    var curveStyle = style['curve-style'].value;\n    var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';\n\n    // ignore edges who are not to be displayed\n    // they shouldn't take up space\n    if( style.display.value === 'none' ){\n      continue;\n    }\n\n    if( style['edge-text-rotation'].strValue === 'autorotate' ){\n      autorotateEdges.push( edge );\n    }\n\n    if( curveStyle === 'haystack' ){\n      haystackEdges.push( edge );\n      continue;\n    }\n\n    var srcId = data.source;\n    var tgtId = data.target;\n\n    pairId = srcId > tgtId ?\n      tgtId + '$-$' + srcId :\n      srcId + '$-$' + tgtId ;\n\n    if( edgeIsUnbundled ){\n      pairId = 'unbundled' + '$-$' + data.id;\n    }\n\n    if( hashTable[pairId] == null ){\n      hashTable[pairId] = [];\n      pairIds.push( pairId );\n    }\n\n    hashTable[pairId].push( edge );\n\n    if( edgeIsUnbundled ){\n      hashTable[pairId].hasUnbundled = true;\n    }\n  }\n\n  var src, tgt, src_p, tgt_p, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape;\n  var vectorNormInverse;\n  var badBezier;\n\n  // for each pair (src, tgt), create the ctrl pts\n  // Nested for loop is OK; total number of iterations for both loops = edgeCount\n  for (var p = 0; p < pairIds.length; p++) {\n    pairId = pairIds[p];\n    var pairEdges = hashTable[pairId];\n\n    // for each pair id, the edges should be sorted by index\n    pairEdges.sort(function(edge1, edge2){\n      return edge1._private.index - edge2._private.index;\n    });\n\n    src = pairEdges[0]._private.source;\n    tgt = pairEdges[0]._private.target;\n\n    src_p = src._private;\n    tgt_p = tgt._private;\n\n    // make sure src/tgt distinction is consistent\n    // (src/tgt in this case are just for ctrlpts and don't actually have to be true src/tgt)\n    if( src_p.data.id > tgt_p.data.id ){\n      var temp = src;\n      src = tgt;\n      tgt = temp;\n    }\n\n    srcPos = src_p.position;\n    tgtPos = tgt_p.position;\n\n    srcW = src.outerWidth();\n    srcH = src.outerHeight();\n\n    tgtW = tgt.outerWidth();\n    tgtH = tgt.outerHeight();\n\n    srcShape = r.nodeShapes[ this.getNodeShape(src) ];\n    tgtShape = r.nodeShapes[ this.getNodeShape(tgt) ];\n\n    badBezier = false;\n\n\n    if( (pairEdges.length > 1 && src !== tgt) || pairEdges.hasUnbundled ){\n\n      // pt outside src shape to calc distance/displacement from src to tgt\n      var srcOutside = srcShape.intersectLine(\n        srcPos.x,\n        srcPos.y,\n        srcW,\n        srcH,\n        tgtPos.x,\n        tgtPos.y,\n        0\n      );\n\n      // pt outside tgt shape to calc distance/displacement from src to tgt\n      var tgtOutside = tgtShape.intersectLine(\n        tgtPos.x,\n        tgtPos.y,\n        tgtW,\n        tgtH,\n        srcPos.x,\n        srcPos.y,\n        0\n      );\n\n      var midptSrcPts = {\n        x1: srcOutside[0],\n        x2: tgtOutside[0],\n        y1: srcOutside[1],\n        y2: tgtOutside[1]\n      };\n\n      var dy = ( tgtOutside[1] - srcOutside[1] );\n      var dx = ( tgtOutside[0] - srcOutside[0] );\n      var l = Math.sqrt( dx*dx + dy*dy );\n\n      var vector = {\n        x: dx,\n        y: dy\n      };\n\n      var vectorNorm = {\n        x: vector.x/l,\n        y: vector.y/l\n      };\n      vectorNormInverse = {\n        x: -vectorNorm.y,\n        y: vectorNorm.x\n      };\n\n\n      // if src intersection is inside tgt or tgt intersection is inside src, then no ctrl pts to draw\n      if(\n        tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y )  ||\n        srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y )\n      ){\n        vectorNormInverse = {};\n        badBezier = true;\n      }\n\n    }\n\n    var edge;\n    var edge_p;\n    var rs;\n\n    for (var i = 0; i < pairEdges.length; i++) {\n      edge = pairEdges[i];\n      edge_p = edge._private;\n      rs = edge_p.rscratch;\n\n      var edgeIndex1 = rs.lastEdgeIndex;\n      var edgeIndex2 = i;\n\n      var numEdges1 = rs.lastNumEdges;\n      var numEdges2 = pairEdges.length;\n\n      var eStyle = edge_p.style;\n      var style = eStyle;\n      var curveStyle = eStyle['curve-style'].value;\n      var ctrlptDists = eStyle['control-point-distances'];\n      var ctrlptWs = eStyle['control-point-weights'];\n      var bezierN = ctrlptDists && ctrlptWs ? Math.min( ctrlptDists.value.length, ctrlptWs.value.length ) : 1;\n      var stepSize = eStyle['control-point-step-size'].pfValue;\n      var ctrlptDist = ctrlptDists !== undefined ? ctrlptDists.pfValue[0] : undefined;\n      var ctrlptWeight = ctrlptWs.value[0];\n      var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';\n\n      var swappedDirection = edge_p.source !== src;\n\n      if( swappedDirection && edgeIsUnbundled ){\n        ctrlptDist *= -1;\n      }\n\n      var srcX1 = rs.lastSrcCtlPtX;\n      var srcX2 = srcPos.x;\n      var srcY1 = rs.lastSrcCtlPtY;\n      var srcY2 = srcPos.y;\n      var srcW1 = rs.lastSrcCtlPtW;\n      var srcW2 = src.outerWidth();\n      var srcH1 = rs.lastSrcCtlPtH;\n      var srcH2 = src.outerHeight();\n\n      var tgtX1 = rs.lastTgtCtlPtX;\n      var tgtX2 = tgtPos.x;\n      var tgtY1 = rs.lastTgtCtlPtY;\n      var tgtY2 = tgtPos.y;\n      var tgtW1 = rs.lastTgtCtlPtW;\n      var tgtW2 = tgt.outerWidth();\n      var tgtH1 = rs.lastTgtCtlPtH;\n      var tgtH2 = tgt.outerHeight();\n\n      var width1 = rs.lastW;\n      var width2 = eStyle['control-point-step-size'].pfValue;\n\n      if( badBezier ){\n        rs.badBezier = true;\n      } else {\n        rs.badBezier = false;\n      }\n\n      if( srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2\n      &&  tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2\n      &&  width1 === width2\n      &&  ((edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2) || edgeIsUnbundled) ){\n        // console.log('edge ctrl pt cache HIT')\n        continue; // then the control points haven't changed and we can skip calculating them\n      } else {\n        rs.lastSrcCtlPtX = srcX2;\n        rs.lastSrcCtlPtY = srcY2;\n        rs.lastSrcCtlPtW = srcW2;\n        rs.lastSrcCtlPtH = srcH2;\n        rs.lastTgtCtlPtX = tgtX2;\n        rs.lastTgtCtlPtY = tgtY2;\n        rs.lastTgtCtlPtW = tgtW2;\n        rs.lastTgtCtlPtH = tgtH2;\n        rs.lastEdgeIndex = edgeIndex2;\n        rs.lastNumEdges = numEdges2;\n        rs.lastWidth = width2;\n        // console.log('edge ctrl pt cache MISS')\n      }\n\n      if( src === tgt ){\n        // Self-edge\n\n        rs.edgeType = 'self';\n\n        var j = i;\n        var loopDist = stepSize;\n\n        if( edgeIsUnbundled ){\n          j = 0;\n          loopDist = ctrlptDist;\n        }\n\n        rs.ctrlpts = [\n          srcPos.x,\n          srcPos.y - (1 + Math.pow(srcH, 1.12) / 100) * loopDist * (j / 3 + 1),\n\n          srcPos.x - (1 + Math.pow(srcW, 1.12) / 100) * loopDist * (j / 3 + 1),\n          srcPos.y\n        ];\n\n      } else if(\n        hasCompounds &&\n        ( src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild() ) &&\n        ( src.parents().anySame(tgt) || tgt.parents().anySame(src) )\n      ){\n        // Compound edge\n\n        rs.edgeType = 'compound';\n\n        // because the line approximation doesn't apply for compound beziers\n        // (loop/self edges are already elided b/c of cheap src==tgt check)\n        rs.badBezier = false;\n\n        var j = i;\n        var loopDist = stepSize;\n\n        if( edgeIsUnbundled ){\n          j = 0;\n          loopDist = ctrlptDist;\n        }\n\n        var loopW = 50;\n\n        var loopaPos = {\n          x: srcPos.x - srcW/2,\n          y: srcPos.y - srcH/2\n        };\n\n        var loopbPos = {\n          x: tgtPos.x - tgtW/2,\n          y: tgtPos.y - tgtH/2\n        };\n\n        var loopPos = {\n          x: Math.min( loopaPos.x, loopbPos.x ),\n          y: Math.min( loopaPos.y, loopbPos.y )\n        };\n\n        // avoids cases with impossible beziers\n        var minCompoundStretch = 0.5;\n        var compoundStretchA = Math.max( minCompoundStretch, Math.log(srcW * 0.01) );\n        var compoundStretchB = Math.max( minCompoundStretch, Math.log(tgtW * 0.01) );\n\n        rs.ctrlpts = [\n          loopPos.x,\n          loopPos.y - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchA,\n\n          loopPos.x - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchB,\n          loopPos.y\n        ];\n\n      } else if( curveStyle === 'segments' ){\n        // Segments (multiple straight lines)\n\n        rs.edgeType = 'segments';\n        rs.segpts = [];\n\n        var segmentWs = eStyle['segment-weights'].pfValue;\n        var segmentDs = eStyle['segment-distances'].pfValue;\n        var segmentsN = Math.min( segmentWs.length, segmentDs.length );\n\n        for( var s = 0; s < segmentsN; s++ ){\n          var w = segmentWs[s];\n          var d = segmentDs[s];\n\n          // d = swappedDirection ? -d : d;\n          //\n          // d = Math.abs(d);\n\n          // var w1 = !swappedDirection ? (1 - w) : w;\n          // var w2 = !swappedDirection ? w : (1 - w);\n\n          var w1 = (1 - w);\n          var w2 = w;\n\n          var adjustedMidpt = {\n            x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,\n            y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2\n          };\n\n          rs.segpts.push(\n            adjustedMidpt.x + vectorNormInverse.x * d,\n            adjustedMidpt.y + vectorNormInverse.y * d\n          );\n        }\n\n      // Straight edge\n      } else if (\n        pairEdges.length % 2 === 1\n        && i === Math.floor(pairEdges.length / 2)\n        && !edgeIsUnbundled\n      ){\n\n        rs.edgeType = 'straight';\n\n      } else {\n        // (Multi)bezier\n\n        var multi = edgeIsUnbundled;\n\n        rs.edgeType = multi ? 'multibezier' : 'bezier';\n        rs.ctrlpts = [];\n\n        for( var b = 0; b < bezierN; b++ ){\n          var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize;\n          var manctrlptDist;\n          var sign = math.signum( normctrlptDist );\n\n          if( multi ){\n            ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[b] : stepSize; // fall back on step size\n            ctrlptWeight = ctrlptWs.value[b];\n          }\n\n          if( edgeIsUnbundled ){ // multi or single unbundled\n            manctrlptDist = ctrlptDist;\n          } else {\n            manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined;\n          }\n\n          var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist;\n\n          var w1 = !swappedDirection || edgeIsUnbundled ? (1 - ctrlptWeight) : ctrlptWeight;\n          var w2 = !swappedDirection || edgeIsUnbundled ? ctrlptWeight : (1 - ctrlptWeight);\n\n          var adjustedMidpt = {\n            x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,\n            y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2\n          };\n\n          rs.ctrlpts.push(\n            adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint,\n            adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint\n          );\n        }\n\n      }\n\n      // find endpts for edge\n      this.findEndpoints( edge );\n\n      var badStart = !is.number( rs.startX ) || !is.number( rs.startY );\n      var badAStart = !is.number( rs.arrowStartX ) || !is.number( rs.arrowStartY );\n      var badEnd = !is.number( rs.endX ) || !is.number( rs.endY );\n      var badAEnd = !is.number( rs.arrowEndX ) || !is.number( rs.arrowEndY );\n\n      var minCpADistFactor = 3;\n      var arrowW = this.getArrowWidth( eStyle['width'].pfValue ) * this.arrowShapeHeight;\n      var minCpADist = minCpADistFactor * arrowW;\n\n      if( rs.edgeType === 'bezier' ){\n        var startACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY } );\n        var closeStartACp = startACpDist < minCpADist;\n        var endACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY } );\n        var closeEndACp = endACpDist < minCpADist;\n\n        var overlapping = false;\n\n        if( badStart || badAStart || closeStartACp ){\n          overlapping = true;\n\n          // project control point along line from src centre to outside the src shape\n          // (otherwise intersection will yield nothing)\n          var cpD = { // delta\n            x: rs.ctrlpts[0] - srcPos.x,\n            y: rs.ctrlpts[1] - srcPos.y\n          };\n          var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line\n          var cpM = { // normalised delta\n            x: cpD.x / cpL,\n            y: cpD.y / cpL\n          };\n          var radius = Math.max(srcW, srcH);\n          var cpProj = { // *2 radius guarantees outside shape\n            x: rs.ctrlpts[0] + cpM.x * 2 * radius,\n            y: rs.ctrlpts[1] + cpM.y * 2 * radius\n          };\n\n          var srcCtrlPtIntn = srcShape.intersectLine(\n            srcPos.x,\n            srcPos.y,\n            srcW,\n            srcH,\n            cpProj.x,\n            cpProj.y,\n            0\n          );\n\n          if( closeStartACp ){\n            rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist);\n            rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist);\n          } else {\n            rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist;\n            rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist;\n          }\n        }\n\n        if( badEnd || badAEnd || closeEndACp ){\n          overlapping = true;\n\n          // project control point along line from tgt centre to outside the tgt shape\n          // (otherwise intersection will yield nothing)\n          var cpD = { // delta\n            x: rs.ctrlpts[0] - tgtPos.x,\n            y: rs.ctrlpts[1] - tgtPos.y\n          };\n          var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line\n          var cpM = { // normalised delta\n            x: cpD.x / cpL,\n            y: cpD.y / cpL\n          };\n          var radius = Math.max(srcW, srcH);\n          var cpProj = { // *2 radius guarantees outside shape\n            x: rs.ctrlpts[0] + cpM.x * 2 * radius,\n            y: rs.ctrlpts[1] + cpM.y * 2 * radius\n          };\n\n          var tgtCtrlPtIntn = tgtShape.intersectLine(\n            tgtPos.x,\n            tgtPos.y,\n            tgtW,\n            tgtH,\n            cpProj.x,\n            cpProj.y,\n            0\n          );\n\n          if( closeEndACp ){\n            rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist);\n            rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist);\n          } else {\n            rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist;\n            rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist;\n          }\n\n        }\n\n        if( overlapping ){\n          // recalc endpts\n          this.findEndpoints( edge );\n        }\n\n      }\n\n      if( rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n        rs.allpts = [];\n\n        rs.allpts.push( rs.startX, rs.startY );\n\n        for( var b = 0; b+1 < rs.ctrlpts.length; b += 2 ){\n          // ctrl pt itself\n          rs.allpts.push( rs.ctrlpts[b], rs.ctrlpts[b+1] );\n\n          // the midpt between ctrlpts as intermediate destination pts\n          if( b + 3 < rs.ctrlpts.length ){\n            rs.allpts.push( (rs.ctrlpts[b] + rs.ctrlpts[b+2])/2, (rs.ctrlpts[b+1] + rs.ctrlpts[b+3])/2 );\n          }\n        }\n\n        rs.allpts.push( rs.endX, rs.endY );\n\n        var m, mt;\n        if( rs.edgeType === 'bezier' ){\n          rs.midX = math.qbezierAt( rs.arrowStartX, rs.ctrlpts[0], rs.arrowEndX, 0.5 );\n          rs.midY = math.qbezierAt( rs.arrowStartY, rs.ctrlpts[1], rs.arrowEndY, 0.5 );\n        } else if( rs.ctrlpts.length/2 % 2 === 0 ){\n          m = rs.allpts.length/2 - 1;\n\n          rs.midX = rs.allpts[m];\n          rs.midY = rs.allpts[m+1];\n        } else {\n          m = rs.allpts.length/2 - 3;\n          mt = 0.5;\n\n          rs.midX = math.qbezierAt( rs.allpts[m], rs.allpts[m+2], rs.allpts[m+4], mt );\n          rs.midY = math.qbezierAt( rs.allpts[m+1], rs.allpts[m+3], rs.allpts[m+5], mt );\n        }\n\n      } else if( rs.edgeType === 'straight' ){\n        // need to calc these after endpts\n        rs.allpts = [ rs.startX, rs.startY, rs.endX, rs.endY ];\n\n        // default midpt for labels etc\n        rs.midX = ( rs.arrowStartX + rs.arrowEndX )/2;\n        rs.midY = ( rs.arrowStartY + rs.arrowEndY )/2;\n\n      } else if( rs.edgeType === 'segments' ){\n        rs.allpts = [];\n        rs.allpts.push( rs.startX, rs.startY );\n        rs.allpts.push.apply( rs.allpts, rs.segpts );\n        rs.allpts.push( rs.endX, rs.endY );\n\n        if( rs.segpts.length % 4 === 0 ){\n          var i2 = rs.segpts.length / 2;\n          var i1 = i2 - 2;\n\n          rs.midX = ( rs.segpts[i1] + rs.segpts[i2] ) / 2;\n          rs.midY = ( rs.segpts[i1+1] + rs.segpts[i2+1] ) / 2;\n        } else {\n          var i1 = rs.segpts.length / 2 - 1;\n\n          rs.midX = rs.segpts[i1];\n          rs.midY = rs.segpts[i1+1];\n        }\n\n\n      }\n\n      this.projectLines( edge );\n      this.calculateArrowAngles( edge );\n      this.recalculateEdgeLabelProjection( edge );\n\n    }\n  }\n\n  for( var i = 0; i < haystackEdges.length; i++ ){\n    var edge = haystackEdges[i];\n    var _p = edge._private;\n    var style = _p.style;\n    var rscratch = _p.rscratch;\n    var rs = rscratch;\n\n    if( !rscratch.haystack ){\n      var angle = Math.random() * 2 * Math.PI;\n\n      rscratch.source = {\n        x: Math.cos(angle),\n        y: Math.sin(angle)\n      };\n\n      var angle = Math.random() * 2 * Math.PI;\n\n      rscratch.target = {\n        x: Math.cos(angle),\n        y: Math.sin(angle)\n      };\n\n    }\n\n    var src = _p.source;\n    var tgt = _p.target;\n    var srcPos = src._private.position;\n    var tgtPos = tgt._private.position;\n    var srcW = src.width();\n    var tgtW = tgt.width();\n    var srcH = src.height();\n    var tgtH = tgt.height();\n    var radius = style['haystack-radius'].value;\n    var halfRadius = radius/2; // b/c have to half width/height\n\n    rs.haystackPts = rs.allpts = [\n      rs.source.x * srcW * halfRadius + srcPos.x,\n      rs.source.y * srcH * halfRadius + srcPos.y,\n      rs.target.x * tgtW * halfRadius + tgtPos.x,\n      rs.target.y * tgtH * halfRadius + tgtPos.y\n    ];\n\n    rs.midX = (rs.allpts[0] + rs.allpts[2])/2;\n    rs.midY = (rs.allpts[1] + rs.allpts[3])/2;\n\n    // always override as haystack in case set to different type previously\n    rscratch.edgeType = 'haystack';\n    rscratch.haystack = true;\n\n    this.projectLines( edge );\n    this.calculateArrowAngles( edge );\n    this.recalculateEdgeLabelProjection( edge );\n  }\n\n  for( var i = 0 ; i < autorotateEdges.length; i++ ){\n    var edge = autorotateEdges[i];\n    var rs = edge._private.rscratch;\n\n    rs.labelAngle = Math.atan( rs.midDispY / rs.midDispX );\n  }\n\n  return hashTable;\n};\n\nvar getAngleFromDisp = function( dispX, dispY ){\n  return Math.atan2( dispY, dispX ) - Math.PI/2;\n};\n\nBRp.calculateArrowAngles = function( edge ){\n  var rs = edge._private.rscratch;\n  var isHaystack = rs.edgeType === 'haystack';\n  var isMultibezier = rs.edgeType === 'multibezier';\n  var isSegments = rs.edgeType === 'segments';\n  var isCompound = rs.edgeType === 'compound';\n  var isSelf = rs.edgeType === 'self';\n\n  // Displacement gives direction for arrowhead orientation\n  var dispX, dispY;\n  var startX, startY, endX, endY;\n\n  var srcPos = edge.source().position();\n  var tgtPos = edge.target().position();\n\n  if( isHaystack ){\n    startX = rs.haystackPts[0];\n    startY = rs.haystackPts[1];\n    endX = rs.haystackPts[2];\n    endY = rs.haystackPts[3];\n  } else {\n    startX = rs.arrowStartX;\n    startY = rs.arrowStartY;\n    endX = rs.arrowEndX;\n    endY = rs.arrowEndY;\n  }\n\n  // source\n  //\n\n  dispX = srcPos.x - startX;\n  dispY = srcPos.y - startY;\n\n  rs.srcArrowAngle = getAngleFromDisp( dispX, dispY );\n\n  // mid target\n  //\n\n  var midX = rs.midX;\n  var midY = rs.midY;\n\n  if( isHaystack ){\n    midX = ( startX + endX )/2;\n    midY = ( startY + endY )/2;\n  }\n\n  dispX = endX - startX;\n  dispY = endY - startY;\n\n  if( isSelf ){\n    dispX = -1;\n    dispY = 1;\n  } else if( isSegments ){\n    var pts = rs.allpts;\n\n    if( pts.length / 2 % 2 === 0 ){\n      var i2 = pts.length / 2;\n      var i1 = i2 - 2;\n\n      dispX = ( pts[i2] - pts[i1] );\n      dispY = ( pts[i2+1] - pts[i1+1] );\n    } else {\n      var i2 = pts.length / 2 - 1;\n      var i1 = i2 - 2;\n      var i3 = i2 + 2;\n\n      dispX = ( pts[i2] - pts[i1] );\n      dispY = ( pts[i2+1] - pts[i1+1] );\n    }\n  } else if( isMultibezier || isCompound ){\n    var pts = rs.allpts;\n    var cpts = rs.ctrlpts;\n    var bp0x, bp0y;\n    var bp1x, bp1y;\n\n    if( cpts.length / 2 % 2 === 0 ){\n      var p0 = pts.length / 2 - 1; // startpt\n      var ic = p0 + 2;\n      var p1 = ic + 2;\n\n      bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0 );\n      bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0 );\n\n      bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0001 );\n      bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0001 );\n    } else {\n      var ic = pts.length / 2 - 1; // ctrpt\n      var p0 = ic - 2; // startpt\n      var p1 = ic + 2; // endpt\n\n      bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.4999 );\n      bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.4999 );\n\n      bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.5 );\n      bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.5 );\n    }\n\n    dispX = ( bp1x - bp0x );\n    dispY = ( bp1y - bp0y );\n  }\n\n  rs.midtgtArrowAngle = getAngleFromDisp( dispX, dispY );\n\n  rs.midDispX = dispX;\n  rs.midDispY = dispY;\n\n  // mid source\n  //\n\n  dispX *= -1;\n  dispY *= -1;\n\n  if( isSegments ){\n    var pts = rs.allpts;\n\n    if( pts.length / 2 % 2 === 0 ){\n      // already ok\n    } else {\n      var i2 = pts.length / 2 - 1;\n      var i3 = i2 + 2;\n\n      dispX = -( pts[i3] - pts[i2] );\n      dispY = -( pts[i3+1] - pts[i2+1] );\n    }\n  }\n\n  rs.midsrcArrowAngle = getAngleFromDisp( dispX, dispY );\n\n  // target\n  //\n\n  dispX = tgtPos.x - endX;\n  dispY = tgtPos.y - endY;\n\n  rs.tgtArrowAngle = getAngleFromDisp( dispX, dispY );\n};\n\n\nBRp.findEndpoints = function( edge ){\n  var r = this;\n  var intersect;\n\n  var source = edge.source()[0];\n  var target = edge.target()[0];\n\n  var src_p = source._private;\n  var tgt_p = target._private;\n\n  var srcPos = src_p.position;\n  var tgtPos = tgt_p.position;\n\n  var tgtArShape = edge._private.style['target-arrow-shape'].value;\n  var srcArShape = edge._private.style['source-arrow-shape'].value;\n\n  var rs = edge._private.rscratch;\n\n  var et = rs.edgeType;\n  var bezier = et === 'bezier' || et === 'multibezier' || et === 'self' || et === 'compound';\n  var multi = et !== 'bezier';\n  var lines = et === 'straight' || et === 'segments';\n  var segments = et === 'segments';\n\n  var p1, p2;\n\n  if( bezier ){\n    var cpStart = [ rs.ctrlpts[0], rs.ctrlpts[1] ];\n    var cpEnd = multi ? [ rs.ctrlpts[rs.ctrlpts.length - 2], rs.ctrlpts[rs.ctrlpts.length - 1] ] : cpStart;\n\n    p1 = cpEnd;\n    p2 = cpStart;\n  } else if( lines ){\n    var srcArrowFromPt = !segments ? [ tgtPos.x, tgtPos.y ] : rs.segpts.slice( 0, 2 );\n    var tgtArrowFromPt = !segments ? [ srcPos.x, srcPos.y ] : rs.segpts.slice( rs.segpts.length - 2 );\n\n    p1 = tgtArrowFromPt;\n    p2 = srcArrowFromPt;\n  }\n\n  intersect = r.nodeShapes[this.getNodeShape(target)].intersectLine(\n    tgtPos.x,\n    tgtPos.y,\n    target.outerWidth(),\n    target.outerHeight(),\n    p1[0],\n    p1[1],\n    0\n  );\n\n  var arrowEnd = math.shortenIntersection(intersect, p1,\n    r.arrowShapes[tgtArShape].spacing(edge));\n  var edgeEnd = math.shortenIntersection(intersect, p1,\n    r.arrowShapes[tgtArShape].gap(edge));\n\n  rs.endX = edgeEnd[0];\n  rs.endY = edgeEnd[1];\n\n  rs.arrowEndX = arrowEnd[0];\n  rs.arrowEndY = arrowEnd[1];\n\n  intersect = r.nodeShapes[this.getNodeShape(source)].intersectLine(\n    srcPos.x,\n    srcPos.y,\n    source.outerWidth(),\n    source.outerHeight(),\n    p2[0],\n    p2[1],\n    0\n  );\n\n  var arrowStart = math.shortenIntersection(\n    intersect, p2,\n    r.arrowShapes[srcArShape].spacing(edge)\n  );\n  var edgeStart = math.shortenIntersection(\n    intersect, p2,\n    r.arrowShapes[srcArShape].gap(edge)\n  );\n\n  rs.startX = edgeStart[0];\n  rs.startY = edgeStart[1];\n\n  rs.arrowStartX = arrowStart[0];\n  rs.arrowStartY = arrowStart[1];\n\n  if( lines ){\n    if( !is.number(rs.startX) || !is.number(rs.startY) || !is.number(rs.endX) || !is.number(rs.endY) ){\n      rs.badLine = true;\n    } else {\n      rs.badLine = false;\n    }\n  }\n};\n\nBRp.getArrowWidth = BRp.getArrowHeight = function(edgeWidth) {\n  var cache = this.arrowWidthCache = this.arrowWidthCache || {};\n\n  var cachedVal = cache[edgeWidth];\n  if( cachedVal ){\n    return cachedVal;\n  }\n\n  cachedVal =  Math.max(Math.pow(edgeWidth * 13.37, 0.9), 29);\n  cache[edgeWidth] = cachedVal;\n\n  return cachedVal;\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar BRp = {};\n\nBRp.getCachedImage = function(url, onLoad) {\n  var r = this;\n  var imageCache = r.imageCache = r.imageCache || {};\n\n  if( imageCache[url] && imageCache[url].image ){\n    return imageCache[url].image;\n  }\n\n  var cache = imageCache[url] = imageCache[url] || {};\n\n  var image = cache.image = new Image();\n  image.addEventListener('load', onLoad);\n  image.src = url;\n\n  return image;\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar is = require('../../../is');\nvar util = require('../../../util');\n\nvar BaseRenderer = function(){};\nvar BR = BaseRenderer;\nvar BRp = BR.prototype;\n\nBRp.clientFunctions = [ 'redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl' ];\n\nBRp.init = function( options ){\n  var r = this;\n\n  r.options = options;\n\n  r.cy = options.cy;\n\n  r.container = options.cy.container();\n\n  r.selection = [undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag\n\n  //--Pointer-related data\n  r.hoverData = {down: null, last: null,\n      downTime: null, triggerMode: null,\n      dragging: false,\n      initialPan: [null, null], capture: false};\n\n  r.dragData = {possibleDragElements: []};\n\n  r.touchData = {\n      start: null, capture: false,\n\n      // These 3 fields related to tap, taphold events\n      startPosition: [null, null, null, null, null, null],\n      singleTouchStartTime: null,\n      singleTouchMoved: true,\n\n      now: [null, null, null, null, null, null],\n      earlier: [null, null, null, null, null, null]\n  };\n\n  r.redraws = 0;\n  r.showFps = options.showFps;\n\n  r.hideEdgesOnViewport = options.hideEdgesOnViewport;\n  r.hideLabelsOnViewport = options.hideLabelsOnViewport;\n  r.textureOnViewport = options.textureOnViewport;\n  r.wheelSensitivity = options.wheelSensitivity;\n  r.motionBlurEnabled = options.motionBlur; // on by default\n  r.forcedPixelRatio = options.pixelRatio;\n  r.motionBlur = true; // for initial kick off\n  r.motionBlurOpacity = options.motionBlurOpacity;\n  r.motionBlurTransparency = 1 - r.motionBlurOpacity;\n  r.motionBlurPxRatio = 1;\n  r.mbPxRBlurry = 1; //0.8;\n  r.minMbLowQualFrames = 4;\n  r.fullQualityMb = false;\n  r.clearedForMotionBlur = [];\n  r.desktopTapThreshold = options.desktopTapThreshold;\n  r.desktopTapThreshold2 = options.desktopTapThreshold * options.desktopTapThreshold;\n  r.touchTapThreshold = options.touchTapThreshold;\n  r.touchTapThreshold2 = options.touchTapThreshold * options.touchTapThreshold;\n  r.tapholdDuration = 500;\n\n  r.bindings = [];\n\n  r.registerNodeShapes();\n  r.registerArrowShapes();\n  r.load();\n};\n\nBRp.notify = function(params) {\n  var types;\n  var r = this;\n\n  if( is.array( params.type ) ){\n    types = params.type;\n\n  } else {\n    types = [ params.type ];\n  }\n\n  for( var i = 0; i < types.length; i++ ){\n    var type = types[i];\n\n    switch( type ){\n      case 'destroy':\n        r.destroy();\n        return;\n\n      case 'add':\n      case 'remove':\n      case 'load':\n        r.updateElementsCache();\n        break;\n\n      case 'viewport':\n        r.redrawHint('select', true);\n        break;\n\n      case 'style':\n        r.updateCachedZSortedEles();\n        break;\n    }\n\n    if( type === 'load' || type === 'resize' ){\n      r.invalidateContainerClientCoordsCache();\n      r.matchCanvasSize(r.container);\n    }\n  } // for\n\n  r.redrawHint('eles', true);\n  r.redrawHint('drag', true);\n\n  this.startRenderLoop();\n\n  this.redraw();\n};\n\nBRp.destroy = function(){\n  this.destroyed = true;\n\n  this.cy.stopAnimationLoop();\n\n  for( var i = 0; i < this.bindings.length; i++ ){\n    var binding = this.bindings[i];\n    var b = binding;\n\n    b.target.removeEventListener(b.event, b.handler, b.useCapture);\n  }\n\n  if( this.removeObserver ){\n    this.removeObserver.disconnect();\n  }\n\n  if( this.labelCalcDiv ){\n    try{\n      document.body.removeChild(this.labelCalcDiv);\n    } catch(e){\n      // ie10 issue #1014\n    }\n  }\n};\n\n[\n  require('./arrow-shapes'),\n  require('./cached-eles'),\n  require('./coord-ele-math'),\n  require('./images'),\n  require('./load-listeners'),\n  require('./node-shapes'),\n  require('./redraw')\n].forEach(function( props ){\n  util.extend( BRp, props );\n});\n\nmodule.exports = BR;\n","'use strict';\n\nvar is = require('../../../is');\nvar util = require('../../../util');\nvar Event = require('../../../event');\nvar Collection = require('../../../collection');\n\nvar BRp = {};\n\nBRp.registerBinding = function(target, event, handler, useCapture){\n  this.bindings.push({\n    target: target,\n    event: event,\n    handler: handler,\n    useCapture: useCapture\n  });\n\n  target.addEventListener(event, handler, useCapture);\n};\n\nBRp.nodeIsDraggable = function(node) {\n  if (node._private.style['opacity'].value !== 0\n    && node._private.style['visibility'].value == 'visible'\n    && node._private.style['display'].value == 'element'\n    && !node.locked()\n    && node.grabbable() ) {\n\n    return true;\n  }\n\n  return false;\n};\n\nBRp.load = function() {\n  var r = this;\n\n  var triggerEvents = function( target, names, e, props ){\n    if( target == null ){\n      target = r.cy;\n    }\n\n    for( var i = 0; i < names.length; i++ ){\n      var name = names[i];\n\n      var event = Event( e, util.extend({ type: name }, props) );\n      target.trigger( event );\n    }\n  };\n\n  var isMultSelKeyDown = function( e ){\n    return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey\n  };\n\n  var getDragListIds = function(opts){\n    var listHasId;\n\n    if( opts.addToList && r.cy.hasCompoundNodes() ){ // only needed for compound graphs\n      if( !opts.addToList.hasId ){ // build ids lookup if doesn't already exist\n        opts.addToList.hasId = {};\n\n        for( var i = 0; i < opts.addToList.length; i++ ){\n          var ele = opts.addToList[i];\n\n          opts.addToList.hasId[ ele.id() ] = true;\n        }\n      }\n\n      listHasId = opts.addToList.hasId;\n    }\n\n    return listHasId || {};\n  };\n\n  // helper function to determine which child nodes and inner edges\n  // of a compound node to be dragged as well as the grabbed and selected nodes\n  var addDescendantsToDrag = function(node, opts){\n    if( !node._private.cy.hasCompoundNodes() ){\n      return;\n    }\n\n    if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do\n\n    var listHasId = getDragListIds( opts );\n\n    var innerNodes = node.descendants();\n\n    for( var i = 0; i < innerNodes.size(); i++ ){\n      var iNode = innerNodes[i];\n      var _p = iNode._private;\n\n      if( opts.inDragLayer ){\n        _p.rscratch.inDragLayer = true;\n      }\n\n      if( opts.addToList && !listHasId[ iNode.id() ] ){\n        opts.addToList.push( iNode );\n        listHasId[ iNode.id() ] = true;\n\n        _p.grabbed = true;\n      }\n\n      var edges = _p.edges;\n      for( var j = 0; opts.inDragLayer && j < edges.length; j++ ){\n        edges[j]._private.rscratch.inDragLayer = true;\n      }\n    }\n  };\n\n  // adds the given nodes, and its edges to the drag layer\n  var addNodeToDrag = function(node, opts){\n\n    var _p = node._private;\n    var listHasId = getDragListIds( opts );\n\n    if( opts.inDragLayer ){\n      _p.rscratch.inDragLayer = true;\n    }\n\n    if( opts.addToList && !listHasId[ node.id() ] ){\n      opts.addToList.push( node );\n      listHasId[ node.id() ] = true;\n\n      _p.grabbed = true;\n    }\n\n    var edges = _p.edges;\n    for( var i = 0; opts.inDragLayer && i < edges.length; i++ ){\n      edges[i]._private.rscratch.inDragLayer = true;\n    }\n\n    addDescendantsToDrag( node, opts ); // always add to drag\n\n    // also add nodes and edges related to the topmost ancestor\n    updateAncestorsInDragLayer( node, {\n      inDragLayer: opts.inDragLayer\n    } );\n  };\n\n  var freeDraggedElements = function( draggedElements ){\n    if( !draggedElements ){ return; }\n\n    for (var i=0; i < draggedElements.length; i++) {\n\n      var dEi_p = draggedElements[i]._private;\n\n      if(dEi_p.group === 'nodes') {\n        dEi_p.rscratch.inDragLayer = false;\n        dEi_p.grabbed = false;\n\n        var sEdges = dEi_p.edges;\n        for( var j = 0; j < sEdges.length; j++ ){ sEdges[j]._private.rscratch.inDragLayer = false; }\n\n        // for compound nodes, also remove related nodes and edges from the drag layer\n        updateAncestorsInDragLayer(draggedElements[i], { inDragLayer: false });\n\n      } else if( dEi_p.group === 'edges' ){\n        dEi_p.rscratch.inDragLayer = false;\n      }\n\n    }\n  };\n\n  // helper function to determine which ancestor nodes and edges should go\n  // to the drag layer (or should be removed from drag layer).\n  var updateAncestorsInDragLayer = function(node, opts) {\n\n    if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do\n\n    // find top-level parent\n    var parent = node;\n\n    if( !node._private.cy.hasCompoundNodes() ){\n      return;\n    }\n\n    while( parent.parent().nonempty() ){\n      parent = parent.parent()[0];\n    }\n\n    // no parent node: no nodes to add to the drag layer\n    if( parent == node ){\n      return;\n    }\n\n    var nodes = parent.descendants()\n      .merge( parent )\n      .unmerge( node )\n      .unmerge( node.descendants() )\n    ;\n\n    var edges = nodes.connectedEdges();\n\n    var listHasId = getDragListIds( opts );\n\n    for( var i = 0; i < nodes.size(); i++ ){\n      if( opts.inDragLayer !== undefined ){\n        nodes[i]._private.rscratch.inDragLayer = opts.inDragLayer;\n      }\n\n      if( opts.addToList && !listHasId[ nodes[i].id() ] ){\n        opts.addToList.push( nodes[i] );\n        listHasId[ nodes[i].id() ] = true;\n\n        nodes[i]._private.grabbed = true;\n      }\n    }\n\n    for( var j = 0; opts.inDragLayer !== undefined && j < edges.length; j++ ) {\n      edges[j]._private.rscratch.inDragLayer = opts.inDragLayer;\n    }\n  };\n\n  if( typeof MutationObserver !== 'undefined' ){\n    r.removeObserver = new MutationObserver(function( mutns ){\n      for( var i = 0; i < mutns.length; i++ ){\n        var mutn = mutns[i];\n        var rNodes = mutn.removedNodes;\n\n        if( rNodes ){ for( var j = 0; j < rNodes.length; j++ ){\n          var rNode = rNodes[j];\n\n          if( rNode === r.container ){\n            r.destroy();\n            break;\n          }\n        } }\n      }\n    });\n\n    if( r.container.parentNode ){\n      r.removeObserver.observe( r.container.parentNode, { childList: true } );\n    }\n  } else {\n    r.registerBinding(r.container, 'DOMNodeRemoved', function(e){\n      r.destroy();\n    });\n  }\n\n\n\n  // auto resize\n  r.registerBinding(window, 'resize', util.debounce( function(e) {\n    r.invalidateContainerClientCoordsCache();\n\n    r.matchCanvasSize(r.container);\n    r.redrawHint('eles', true);\n    r.redraw();\n  }, 100 ) );\n\n  var invalCtnrBBOnScroll = function(domEle){\n    r.registerBinding(domEle, 'scroll', function(e){\n      r.invalidateContainerClientCoordsCache();\n    } );\n  };\n\n  var bbCtnr = r.cy.container();\n\n  for( ;; ){\n\n    invalCtnrBBOnScroll( bbCtnr );\n\n    if( bbCtnr.parentNode ){\n      bbCtnr = bbCtnr.parentNode;\n    } else {\n      break;\n    }\n\n  }\n\n  // stop right click menu from appearing on cy\n  r.registerBinding(r.container, 'contextmenu', function(e){\n    e.preventDefault();\n  });\n\n  var inBoxSelection = function(){\n    return r.selection[4] !== 0;\n  };\n\n  // Primary key\n  r.registerBinding(r.container, 'mousedown', function(e) {\n    e.preventDefault();\n    r.hoverData.capture = true;\n    r.hoverData.which = e.which;\n\n    var cy = r.cy;\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n    var select = r.selection;\n    var near = r.findNearestElement(pos[0], pos[1], true, false);\n    var draggedElements = r.dragData.possibleDragElements;\n\n    r.hoverData.mdownPos = pos;\n\n    var checkForTaphold = function(){\n      r.hoverData.tapholdCancelled = false;\n\n      clearTimeout( r.hoverData.tapholdTimeout );\n\n      r.hoverData.tapholdTimeout = setTimeout(function(){\n\n        if( r.hoverData.tapholdCancelled ){\n          return;\n        } else {\n          var ele = r.hoverData.down;\n\n          if( ele ){\n            ele.trigger( Event(e, {\n              type: 'taphold',\n              cyPosition: { x: pos[0], y: pos[1] }\n            }) );\n          } else {\n            cy.trigger( Event(e, {\n              type: 'taphold',\n              cyPosition: { x: pos[0], y: pos[1] }\n            }) );\n          }\n        }\n\n      }, r.tapholdDuration);\n    };\n\n    // Right click button\n    if( e.which == 3 ){\n\n      r.hoverData.cxtStarted = true;\n\n      var cxtEvt = Event(e, {\n        type: 'cxttapstart',\n        cyPosition: { x: pos[0], y: pos[1] }\n      });\n\n      if( near ){\n        near.activate();\n        near.trigger( cxtEvt );\n\n        r.hoverData.down = near;\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      r.hoverData.downTime = (new Date()).getTime();\n      r.hoverData.cxtDragged = false;\n\n    // Primary button\n    } else if (e.which == 1) {\n\n      if( near ){\n        near.activate();\n      }\n\n      // Element dragging\n      {\n        // If something is under the cursor and it is draggable, prepare to grab it\n        if (near != null) {\n\n          if( r.nodeIsDraggable(near) ){\n\n            var grabEvent = Event(e, {\n              type: 'grab',\n              cyPosition: { x: pos[0], y: pos[1] }\n            });\n\n            if ( near.isNode() && !near.selected() ){\n\n              draggedElements = r.dragData.possibleDragElements = [];\n              addNodeToDrag( near, { addToList: draggedElements } );\n\n              near.trigger(grabEvent);\n\n            } else if ( near.isNode() && near.selected() ){\n              draggedElements = r.dragData.possibleDragElements = [  ];\n\n              var selectedNodes = cy.$(function(){ return this.isNode() && this.selected(); });\n\n              for( var i = 0; i < selectedNodes.length; i++ ){\n\n                // Only add this selected node to drag if it is draggable, eg. has nonzero opacity\n                if( r.nodeIsDraggable( selectedNodes[i] ) ){\n                  addNodeToDrag( selectedNodes[i], { addToList: draggedElements } );\n                }\n              }\n\n              near.trigger( grabEvent );\n            }\n\n            r.redrawHint('eles', true);\n            r.redrawHint('drag', true);\n\n          }\n\n        }\n\n        r.hoverData.down = near;\n        r.hoverData.downTime = (new Date()).getTime();\n      }\n\n      triggerEvents( near, ['mousedown', 'tapstart', 'vmousedown'], e, {\n        cyPosition: { x: pos[0], y: pos[1] }\n      } );\n\n      if ( near == null ) {\n        select[4] = 1;\n\n        r.data.bgActivePosistion = {\n          x: pos[0],\n          y: pos[1]\n        };\n\n        r.redrawHint('select', true);\n\n        r.redraw();\n      } else if( near.isEdge() ){\n        select[4] = 1; // for future pan\n      }\n\n      checkForTaphold();\n\n    }\n\n    // Initialize selection box coordinates\n    select[0] = select[2] = pos[0];\n    select[1] = select[3] = pos[1];\n\n  }, false);\n\n  r.registerBinding(window, 'mousemove', function(e) {\n    var preventDefault = false;\n    var capture = r.hoverData.capture;\n\n    // save cycles if mouse events aren't to be captured\n    if ( !capture ){\n      var containerPageCoords = r.findContainerClientCoords();\n\n      if (e.clientX > containerPageCoords[0] && e.clientX < containerPageCoords[0] + r.canvasWidth\n        && e.clientY > containerPageCoords[1] && e.clientY < containerPageCoords[1] + r.canvasHeight\n      ) {\n        // inside container bounds so OK\n      } else {\n        return;\n      }\n\n      var cyContainer = r.container;\n      var target = e.target;\n      var tParent = target.parentNode;\n      var containerIsTarget = false;\n\n      while( tParent ){\n        if( tParent === cyContainer ){\n          containerIsTarget = true;\n          break;\n        }\n\n        tParent = tParent.parentNode;\n      }\n\n      if( !containerIsTarget ){ return; } // if target is outisde cy container, then this event is not for us\n    }\n\n    var cy = r.cy;\n    var zoom = cy.zoom();\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n    var select = r.selection;\n\n    var near = null;\n    if( !r.hoverData.draggingEles ){\n      near = r.findNearestElement(pos[0], pos[1], true, false);\n    }\n    var last = r.hoverData.last;\n    var down = r.hoverData.down;\n\n    var disp = [pos[0] - select[2], pos[1] - select[3]];\n\n    var draggedElements = r.dragData.possibleDragElements;\n\n    var dx = select[2] - select[0];\n    var dx2 = dx * dx;\n    var dy = select[3] - select[1];\n    var dy2 = dy * dy;\n    var dist2 = dx2 + dy2;\n    var rdist2 = dist2 * zoom * zoom;\n\n    var multSelKeyDown = isMultSelKeyDown( e );\n\n    r.hoverData.tapholdCancelled = true;\n\n    var updateDragDelta = function(){\n      var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || [];\n\n      if( dragDelta.length === 0 ){\n        dragDelta.push( disp[0] );\n        dragDelta.push( disp[1] );\n      } else {\n        dragDelta[0] += disp[0];\n        dragDelta[1] += disp[1];\n      }\n    };\n\n\n    preventDefault = true;\n\n    triggerEvents( near, ['mousemove', 'vmousemove', 'tapdrag'], e, {\n      cyPosition: { x: pos[0], y: pos[1] }\n    } );\n\n    // trigger context drag if rmouse down\n    if( r.hoverData.which === 3 ){\n      var cxtEvt = Event(e, {\n        type: 'cxtdrag',\n        cyPosition: { x: pos[0], y: pos[1] }\n      });\n\n      if( down ){\n        down.trigger( cxtEvt );\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      r.hoverData.cxtDragged = true;\n\n      if( !r.hoverData.cxtOver || near !== r.hoverData.cxtOver ){\n\n        if( r.hoverData.cxtOver ){\n          r.hoverData.cxtOver.trigger( Event(e, {\n            type: 'cxtdragout',\n            cyPosition: { x: pos[0], y: pos[1] }\n          }) );\n        }\n\n        r.hoverData.cxtOver = near;\n\n        if( near ){\n          near.trigger( Event(e, {\n            type: 'cxtdragover',\n            cyPosition: { x: pos[0], y: pos[1] }\n          }) );\n        }\n\n      }\n\n    // Check if we are drag panning the entire graph\n    } else if (r.hoverData.dragging) {\n      preventDefault = true;\n\n      if( cy.panningEnabled() && cy.userPanningEnabled() ){\n        var deltaP;\n\n        if( r.hoverData.justStartedPan ){\n          var mdPos = r.hoverData.mdownPos;\n\n          deltaP = {\n            x: ( pos[0] - mdPos[0] ) * zoom,\n            y: ( pos[1] - mdPos[1] ) * zoom\n          };\n\n          r.hoverData.justStartedPan = false;\n\n        } else {\n          deltaP = {\n            x: disp[0] * zoom,\n            y: disp[1] * zoom\n          };\n\n        }\n\n        cy.panBy( deltaP );\n\n        r.hoverData.dragged = true;\n      }\n\n      // Needs reproject due to pan changing viewport\n      pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n    // Checks primary button down & out of time & mouse not moved much\n    } else if(\n        select[4] == 1 && (down == null || down.isEdge())\n    ){\n\n      if( !r.hoverData.dragging && cy.boxSelectionEnabled() && ( multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled() ) ){\n        r.data.bgActivePosistion = undefined;\n        r.hoverData.selecting = true;\n\n        r.redrawHint('select', true);\n        r.redraw();\n\n      } else if( !r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled() ){\n        r.hoverData.dragging = true;\n        r.hoverData.justStartedPan = true;\n        select[4] = 0;\n\n        r.data.bgActivePosistion = {\n          x: pos[0],\n          y: pos[1]\n        };\n\n        r.redrawHint('select', true);\n        r.redraw();\n      }\n\n      if( down && down.isEdge() && down.active() ){ down.unactivate(); }\n\n    } else {\n      if( down && down.isEdge() && down.active() ){ down.unactivate(); }\n\n      if (near != last) {\n\n        if (last) {\n          triggerEvents( last, ['mouseout', 'tapdragout'], e, {\n            cyPosition: { x: pos[0], y: pos[1] }\n          } );\n        }\n\n        if (near) {\n          triggerEvents( near, ['mouseover', 'tapdragover'], e, {\n            cyPosition: { x: pos[0], y: pos[1] }\n          } );\n        }\n\n        r.hoverData.last = near;\n      }\n\n      if( down && down.isNode() && r.nodeIsDraggable(down) ){\n\n        if( rdist2 >= r.desktopTapThreshold2 ){ // then drag\n\n          var justStartedDrag = !r.dragData.didDrag;\n\n          if( justStartedDrag ) {\n            r.redrawHint('eles', true);\n          }\n\n          r.dragData.didDrag = true; // indicate that we actually did drag the node\n\n          var toTrigger = [];\n\n          for( var i = 0; i < draggedElements.length; i++ ){\n            var dEle = draggedElements[i];\n\n            // now, add the elements to the drag layer if not done already\n            if( !r.hoverData.draggingEles ){\n              addNodeToDrag( dEle, { inDragLayer: true } );\n            }\n\n            // Locked nodes not draggable, as well as non-visible nodes\n            if( dEle.isNode() && r.nodeIsDraggable(dEle) && dEle.grabbed() ){\n              var dPos = dEle._private.position;\n\n              toTrigger.push( dEle );\n\n              if( is.number(disp[0]) && is.number(disp[1]) ){\n                var updatePos = !dEle.isParent();\n\n                if( updatePos ){\n                  dPos.x += disp[0];\n                  dPos.y += disp[1];\n                }\n\n                if( justStartedDrag ){\n                  var dragDelta = r.hoverData.dragDelta;\n\n                  if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){\n                    dPos.x += dragDelta[0];\n                    dPos.y += dragDelta[1];\n                  }\n                }\n              }\n\n            }\n          }\n\n          r.hoverData.draggingEles = true;\n\n          var tcol = (Collection(cy, toTrigger));\n\n          tcol.updateCompoundBounds();\n          tcol.trigger('position drag');\n\n          r.redrawHint('drag', true);\n          r.redraw();\n\n        } else { // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant\n          updateDragDelta();\n        }\n      }\n\n      // prevent the dragging from triggering text selection on the page\n      preventDefault = true;\n    }\n\n    select[2] = pos[0]; select[3] = pos[1];\n\n    if( preventDefault ){\n      if(e.stopPropagation) e.stopPropagation();\n        if(e.preventDefault) e.preventDefault();\n        return false;\n      }\n  }, false);\n\n  r.registerBinding(window, 'mouseup', function(e) {\n    var capture = r.hoverData.capture;\n    if (!capture) { return; }\n    r.hoverData.capture = false;\n\n    var cy = r.cy; var pos = r.projectIntoViewport(e.clientX, e.clientY); var select = r.selection;\n    var near = r.findNearestElement(pos[0], pos[1], true, false);\n    var draggedElements = r.dragData.possibleDragElements; var down = r.hoverData.down;\n    var multSelKeyDown = isMultSelKeyDown( e );\n\n    if( r.data.bgActivePosistion ){\n      r.redrawHint('select', true);\n      r.redraw();\n    }\n\n    r.hoverData.tapholdCancelled = true;\n\n    r.data.bgActivePosistion = undefined; // not active bg now\n\n    if( down ){\n      down.unactivate();\n    }\n\n    if( r.hoverData.which === 3 ){\n      var cxtEvt = Event(e, {\n        type: 'cxttapend',\n        cyPosition: { x: pos[0], y: pos[1] }\n      });\n\n      if( down ){\n        down.trigger( cxtEvt );\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      if( !r.hoverData.cxtDragged ){\n        var cxtTap = Event(e, {\n          type: 'cxttap',\n          cyPosition: { x: pos[0], y: pos[1] }\n        });\n\n        if( down ){\n          down.trigger( cxtTap );\n        } else {\n          cy.trigger( cxtTap );\n        }\n      }\n\n      r.hoverData.cxtDragged = false;\n      r.hoverData.which = null;\n\n    } else if( r.hoverData.which === 1 ) {\n\n      // Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something\n      if ( (down == null) // not mousedown on node\n        && !r.dragData.didDrag // didn't move the node around\n        && !r.hoverData.selecting // not box selection\n        && !r.hoverData.dragged // didn't pan\n        && !isMultSelKeyDown( e )\n      ) {\n\n        cy.$(function(){\n          return this.selected();\n        }).unselect();\n\n        if (draggedElements.length > 0) {\n          r.redrawHint('eles', true);\n        }\n\n        r.dragData.possibleDragElements = draggedElements = [];\n      }\n\n      triggerEvents( near, ['mouseup', 'tapend', 'vmouseup'], e, {\n        cyPosition: { x: pos[0], y: pos[1] }\n      } );\n\n      if(\n        !r.dragData.didDrag // didn't move a node around\n        && !r.hoverData.dragged // didn't pan\n      ){\n        triggerEvents( near, ['click', 'tap', 'vclick'], e, {\n          cyPosition: { x: pos[0], y: pos[1] }\n        } );\n      }\n\n      // Single selection\n      if( near == down && !r.dragData.didDrag && !r.hoverData.selecting ){\n        if( near != null && near._private.selectable ){\n\n          if( r.hoverData.dragging ){\n            // if panning, don't change selection state\n          } else if( cy.selectionType() === 'additive' || multSelKeyDown ){\n            if( near.selected() ){\n              near.unselect();\n            } else {\n              near.select();\n            }\n          } else {\n            if( !multSelKeyDown ){\n              cy.$(':selected').unmerge( near ).unselect();\n              near.select();\n            }\n          }\n\n          r.redrawHint('eles', true);\n        }\n      }\n\n      if ( r.hoverData.selecting ) {\n        var newlySelected = [];\n        var box = r.getAllInBox( select[0], select[1], select[2], select[3] );\n\n        r.redrawHint('select', true);\n\n        if( box.length > 0 ) {\n          r.redrawHint('eles', true);\n        }\n\n        for( var i = 0; i < box.length; i++ ){\n          if( box[i]._private.selectable ){\n            newlySelected.push( box[i] );\n          }\n        }\n\n        var newlySelCol = Collection( cy, newlySelected );\n\n        if( cy.selectionType() === 'additive' ){\n          newlySelCol.select();\n        } else {\n          if( !multSelKeyDown ){\n            cy.$(':selected').unmerge( newlySelCol ).unselect();\n          }\n\n          newlySelCol.select();\n        }\n\n        // always need redraw in case eles unselectable\n        r.redraw();\n\n      }\n\n      // Cancel drag pan\n      if( r.hoverData.dragging ){\n        r.hoverData.dragging = false;\n\n        r.redrawHint('select', true);\n        r.redrawHint('eles', true);\n\n        r.redraw();\n      }\n\n      if (!select[4]) {\n\n\n        r.redrawHint('drag', true);\n        r.redrawHint('eles', true);\n\n        freeDraggedElements( draggedElements );\n\n        if( down ){ down.trigger('free'); }\n      }\n\n    } // else not right mouse\n\n    select[4] = 0; r.hoverData.down = null;\n\n    r.hoverData.cxtStarted = false;\n    r.hoverData.draggingEles = false;\n    r.hoverData.selecting = false;\n    r.dragData.didDrag = false;\n    r.hoverData.dragged = false;\n    r.hoverData.dragDelta = [];\n\n  }, false);\n\n  var wheelHandler = function(e) {\n\n\n    if( r.scrollingPage ){ return; } // while scrolling, ignore wheel-to-zoom\n\n    var cy = r.cy;\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n    var rpos = [pos[0] * cy.zoom() + cy.pan().x,\n                  pos[1] * cy.zoom() + cy.pan().y];\n\n    if( r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection() ){ // if pan dragging or cxt dragging, wheel movements make no zoom\n      e.preventDefault();\n      return;\n    }\n\n    if( cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled() ){\n      e.preventDefault();\n\n      r.data.wheelZooming = true;\n      clearTimeout( r.data.wheelTimeout );\n      r.data.wheelTimeout = setTimeout(function(){\n        r.data.wheelZooming = false;\n\n        r.redrawHint('eles', true);\n        r.redraw();\n      }, 150);\n\n      var diff = e.deltaY / -250 || e.wheelDeltaY / 1000 || e.wheelDelta / 1000;\n      diff = diff * r.wheelSensitivity;\n\n      var needsWheelFix = e.deltaMode === 1;\n      if( needsWheelFix ){ // fixes slow wheel events on ff/linux and ff/windows\n        diff *= 33;\n      }\n\n      cy.zoom({\n        level: cy.zoom() * Math.pow(10, diff),\n        renderedPosition: { x: rpos[0], y: rpos[1] }\n      });\n    }\n\n  };\n\n  // Functions to help with whether mouse wheel should trigger zooming\n  // --\n  r.registerBinding(r.container, 'wheel', wheelHandler, true);\n\n  // disable nonstandard wheel events\n  // r.registerBinding(r.container, 'mousewheel', wheelHandler, true);\n  // r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true);\n  // r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox\n\n  r.registerBinding(window, 'scroll', function(e){\n    r.scrollingPage = true;\n\n    clearTimeout( r.scrollingPageTimeout );\n    r.scrollingPageTimeout = setTimeout(function(){\n      r.scrollingPage = false;\n    }, 250);\n  }, true);\n\n  // Functions to help with handling mouseout/mouseover on the Cytoscape container\n        // Handle mouseout on Cytoscape container\n  r.registerBinding(r.container, 'mouseout', function(e) {\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n    r.cy.trigger(Event(e, {\n      type: 'mouseout',\n      cyPosition: { x: pos[0], y: pos[1] }\n    }));\n  }, false);\n\n  r.registerBinding(r.container, 'mouseover', function(e) {\n    var pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n    r.cy.trigger(Event(e, {\n      type: 'mouseover',\n      cyPosition: { x: pos[0], y: pos[1] }\n    }));\n  }, false);\n\n  var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom\n  var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom\n  var center1, modelCenter1; // center point on start pinch to zoom\n  var offsetLeft, offsetTop;\n  var containerWidth, containerHeight;\n  var twoFingersStartInside;\n\n  var distance = function(x1, y1, x2, y2){\n    return Math.sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );\n  };\n\n  var distanceSq = function(x1, y1, x2, y2){\n    return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);\n  };\n\n  var touchstartHandler;\n  r.registerBinding(r.container, 'touchstart', touchstartHandler = function(e) {\n    r.touchData.capture = true;\n    r.data.bgActivePosistion = undefined;\n\n    var cy = r.cy;\n    var nodes = r.getCachedNodes();\n    var edges = r.getCachedEdges();\n    var now = r.touchData.now;\n    var earlier = r.touchData.earlier;\n\n    if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n    if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n    if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n\n    // record starting points for pinch-to-zoom\n    if( e.touches[1] ){\n\n      // anything in the set of dragged eles should be released\n      var release = function( eles ){\n        for( var i = 0; i < eles.length; i++ ){\n          eles[i]._private.grabbed = false;\n          eles[i]._private.rscratch.inDragLayer = false;\n          if( eles[i].active() ){ eles[i].unactivate(); }\n        }\n      };\n      release(nodes);\n      release(edges);\n\n      var offsets = r.findContainerClientCoords();\n      offsetLeft = offsets[0];\n      offsetTop = offsets[1];\n      containerWidth = offsets[2];\n      containerHeight = offsets[3];\n\n      f1x1 = e.touches[0].clientX - offsetLeft;\n      f1y1 = e.touches[0].clientY - offsetTop;\n\n      f2x1 = e.touches[1].clientX - offsetLeft;\n      f2y1 = e.touches[1].clientY - offsetTop;\n\n      twoFingersStartInside =\n           0 <= f1x1 && f1x1 <= containerWidth\n        && 0 <= f2x1 && f2x1 <= containerWidth\n        && 0 <= f1y1 && f1y1 <= containerHeight\n        && 0 <= f2y1 && f2y1 <= containerHeight\n      ;\n\n      var pan = cy.pan();\n      var zoom = cy.zoom();\n\n      distance1 = distance( f1x1, f1y1, f2x1, f2y1 );\n      distance1Sq = distanceSq( f1x1, f1y1, f2x1, f2y1 );\n      center1 = [ (f1x1 + f2x1)/2, (f1y1 + f2y1)/2 ];\n      modelCenter1 = [\n        (center1[0] - pan.x) / zoom,\n        (center1[1] - pan.y) / zoom\n      ];\n\n      // consider context tap\n      var cxtDistThreshold = 200;\n      var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold;\n      if( distance1Sq < cxtDistThresholdSq && !e.touches[2] ){\n\n        var near1 = r.findNearestElement(now[0], now[1], true, true);\n        var near2 = r.findNearestElement(now[2], now[3], true, true);\n\n        if( near1 && near1.isNode() ){\n          near1.activate().trigger( Event(e, {\n            type: 'cxttapstart',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n          r.touchData.start = near1;\n\n        } else if( near2 && near2.isNode() ){\n          near2.activate().trigger( Event(e, {\n            type: 'cxttapstart',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n          r.touchData.start = near2;\n\n        } else {\n          cy.trigger( Event(e, {\n            type: 'cxttapstart',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n          r.touchData.start = null;\n        }\n\n        if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n        r.touchData.cxt = true;\n        r.touchData.cxtDragged = false;\n        r.data.bgActivePosistion = undefined;\n\n        r.redraw();\n        return;\n\n      }\n\n    }\n\n    if (e.touches[2]) {\n\n    } else if (e.touches[1]) {\n\n    } else if (e.touches[0]) {\n      var near = r.findNearestElement(now[0], now[1], true, true);\n\n      if (near != null) {\n        near.activate();\n\n        r.touchData.start = near;\n\n        if( near.isNode() && r.nodeIsDraggable(near) ){\n\n          var draggedEles = r.dragData.touchDragEles = [];\n\n          r.redrawHint('eles', true);\n          r.redrawHint('drag', true);\n\n          if( near.selected() ){\n            // reset drag elements, since near will be added again\n\n            var selectedNodes = cy.$(function(){\n              return this.isNode() && this.selected();\n            });\n\n            for( var k = 0; k < selectedNodes.length; k++ ){\n              var selectedNode = selectedNodes[k];\n\n              if( r.nodeIsDraggable(selectedNode) ){\n                addNodeToDrag( selectedNode, { addToList: draggedEles } );\n              }\n            }\n          } else {\n            addNodeToDrag( near, { addToList: draggedEles } );\n          }\n\n          near.trigger( Event(e, {\n            type: 'grab',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n        }\n      }\n\n      triggerEvents( near, ['touchstart', 'tapstart', 'vmousedown'], e, {\n        cyPosition: { x: now[0], y: now[1] }\n      } );\n\n      if (near == null) {\n        r.data.bgActivePosistion = {\n          x: pos[0],\n          y: pos[1]\n        };\n\n        r.redrawHint('select', true);\n        r.redraw();\n      }\n\n\n      // Tap, taphold\n      // -----\n\n      for (var i=0; i<now.length; i++) {\n        earlier[i] = now[i];\n        r.touchData.startPosition[i] = now[i];\n      }\n\n      r.touchData.singleTouchMoved = false;\n      r.touchData.singleTouchStartTime = +new Date();\n\n      clearTimeout( r.touchData.tapholdTimeout );\n      r.touchData.tapholdTimeout = setTimeout(function() {\n        if(\n            r.touchData.singleTouchMoved === false\n            && !r.pinching // if pinching, then taphold unselect shouldn't take effect\n        ){\n          triggerEvents( r.touchData.start, ['taphold'], e, {\n            cyPosition: { x: now[0], y: now[1] }\n          } );\n\n          if (!r.touchData.start) {\n            cy.$(':selected').unselect();\n          }\n\n        }\n      }, r.tapholdDuration);\n    }\n\n  }, false);\n\n  var touchmoveHandler;\n  r.registerBinding(window, 'touchmove', touchmoveHandler = function(e) {\n\n    var select = r.selection;\n    var capture = r.touchData.capture;\n    var cy = r.cy;\n    var now = r.touchData.now; var earlier = r.touchData.earlier;\n    var zoom = cy.zoom();\n\n    if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n    if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n    if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n    var disp = []; for (var j=0;j<now.length;j++) { disp[j] = now[j] - earlier[j]; }\n    var startPos = r.touchData.startPosition;\n    var dx = now[0] - startPos[0];\n    var dx2 = dx * dx;\n    var dy = now[1] - startPos[1];\n    var dy2 = dy * dy;\n    var dist2 = dx2 + dy2;\n    var rdist2 = dist2 * zoom * zoom;\n\n    // context swipe cancelling\n    if( capture && r.touchData.cxt ){\n      e.preventDefault();\n\n      var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop;\n      var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop;\n      // var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );\n      var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );\n      var factorSq = distance2Sq / distance1Sq;\n\n      var distThreshold = 150;\n      var distThresholdSq = distThreshold * distThreshold;\n      var factorThreshold = 1.5;\n      var factorThresholdSq = factorThreshold * factorThreshold;\n\n      // cancel ctx gestures if the distance b/t the fingers increases\n      if( factorSq >= factorThresholdSq || distance2Sq >= distThresholdSq ){\n        r.touchData.cxt = false;\n        if( r.touchData.start ){ r.touchData.start.unactivate(); r.touchData.start = null; }\n        r.data.bgActivePosistion = undefined;\n        r.redrawHint('select', true);\n\n        var cxtEvt = Event(e, {\n          type: 'cxttapend',\n          cyPosition: { x: now[0], y: now[1] }\n        });\n        if( r.touchData.start ){\n          r.touchData.start.trigger( cxtEvt );\n        } else {\n          cy.trigger( cxtEvt );\n        }\n      }\n\n    }\n\n    // context swipe\n    if( capture && r.touchData.cxt ){\n      var cxtEvt = Event(e, {\n        type: 'cxtdrag',\n        cyPosition: { x: now[0], y: now[1] }\n      });\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n\n      if( r.touchData.start ){\n        r.touchData.start.trigger( cxtEvt );\n      } else {\n        cy.trigger( cxtEvt );\n      }\n\n      if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n      r.touchData.cxtDragged = true;\n\n      var near = r.findNearestElement(now[0], now[1], true, true);\n\n      if( !r.touchData.cxtOver || near !== r.touchData.cxtOver ){\n\n        if( r.touchData.cxtOver ){\n          r.touchData.cxtOver.trigger( Event(e, {\n            type: 'cxtdragout',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n        }\n\n        r.touchData.cxtOver = near;\n\n        if( near ){\n          near.trigger( Event(e, {\n            type: 'cxtdragover',\n            cyPosition: { x: now[0], y: now[1] }\n          }) );\n\n        }\n\n      }\n\n    // box selection\n    } else if( capture && e.touches[2] && cy.boxSelectionEnabled() ){\n      e.preventDefault();\n\n      r.data.bgActivePosistion = undefined;\n\n      this.lastThreeTouch = +new Date();\n      r.touchData.selecting = true;\n\n      r.redrawHint('select', true);\n\n      if( !select || select.length === 0 || select[0] === undefined ){\n        select[0] = (now[0] + now[2] + now[4])/3;\n        select[1] = (now[1] + now[3] + now[5])/3;\n        select[2] = (now[0] + now[2] + now[4])/3 + 1;\n        select[3] = (now[1] + now[3] + now[5])/3 + 1;\n      } else {\n        select[2] = (now[0] + now[2] + now[4])/3;\n        select[3] = (now[1] + now[3] + now[5])/3;\n      }\n\n      select[4] = 1;\n      r.touchData.selecting = true;\n\n      r.redraw();\n\n    // pinch to zoom\n    } else if ( capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled() ) { // two fingers => pinch to zoom\n      e.preventDefault();\n\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n\n      var draggedEles = r.dragData.touchDragEles;\n      if( draggedEles ){\n        r.redrawHint('drag', true);\n\n        for( var i = 0; i < draggedEles.length; i++ ){\n          draggedEles[i]._private.grabbed = false;\n          draggedEles[i]._private.rscratch.inDragLayer = false;\n        }\n      }\n\n      // (x2, y2) for fingers 1 and 2\n      var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop;\n      var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop;\n\n\n      var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );\n      // var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );\n      // var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq );\n      var factor = distance2 / distance1;\n\n      if( factor != 1 && twoFingersStartInside){\n        // delta finger1\n        var df1x = f1x2 - f1x1;\n        var df1y = f1y2 - f1y1;\n\n        // delta finger 2\n        var df2x = f2x2 - f2x1;\n        var df2y = f2y2 - f2y1;\n\n        // translation is the normalised vector of the two fingers movement\n        // i.e. so pinching cancels out and moving together pans\n        var tx = (df1x + df2x)/2;\n        var ty = (df1y + df2y)/2;\n\n        // adjust factor by the speed multiplier\n        // var speed = 1.5;\n        // if( factor > 1 ){\n        //   factor = (factor - 1) * speed + 1;\n        // } else {\n        //   factor = 1 - (1 - factor) * speed;\n        // }\n\n        // now calculate the zoom\n        var zoom1 = cy.zoom();\n        var zoom2 = zoom1 * factor;\n        var pan1 = cy.pan();\n\n        // the model center point converted to the current rendered pos\n        var ctrx = modelCenter1[0] * zoom1 + pan1.x;\n        var ctry = modelCenter1[1] * zoom1 + pan1.y;\n\n        var pan2 = {\n          x: -zoom2/zoom1 * (ctrx - pan1.x - tx) + ctrx,\n          y: -zoom2/zoom1 * (ctry - pan1.y - ty) + ctry\n        };\n\n        // remove dragged eles\n        if( r.touchData.start ){\n          var draggedEles = r.dragData.touchDragEles;\n\n          if( draggedEles ){ for( var i = 0; i < draggedEles.length; i++ ){\n            var dEi_p = draggedEles[i]._private;\n\n            dEi_p.grabbed = false;\n            dEi_p.rscratch.inDragLayer = false;\n          } }\n\n          var start_p = r.touchData.start._private;\n          start_p.active = false;\n          start_p.grabbed = false;\n          start_p.rscratch.inDragLayer = false;\n\n          r.redrawHint('drag', true);\n\n          r.touchData.start\n            .trigger('free')\n            .trigger('unactivate')\n          ;\n        }\n\n        cy.viewport({\n          zoom: zoom2,\n          pan: pan2,\n          cancelOnFailedZoom: true\n        });\n\n        distance1 = distance2;\n        f1x1 = f1x2;\n        f1y1 = f1y2;\n        f2x1 = f2x2;\n        f2y1 = f2y2;\n\n        r.pinching = true;\n      }\n\n      // Re-project\n      if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n      if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n      if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n    } else if (e.touches[0]) {\n      var start = r.touchData.start;\n      var last = r.touchData.last;\n      var near = near || r.findNearestElement(now[0], now[1], true, true);\n\n      if( start != null ){\n        e.preventDefault();\n      }\n\n      // dragging nodes\n      if( start != null && start._private.group == 'nodes' && r.nodeIsDraggable(start) ){\n\n        if( rdist2 >= r.touchTapThreshold2 ){ // then dragging can happen\n          var draggedEles = r.dragData.touchDragEles;\n          var justStartedDrag = !r.dragData.didDrag;\n\n          for( var k = 0; k < draggedEles.length; k++ ){\n            var draggedEle = draggedEles[k];\n\n            if( justStartedDrag ){\n              addNodeToDrag( draggedEle, { inDragLayer: true } );\n            }\n\n            if( r.nodeIsDraggable(draggedEle) && draggedEle.isNode() && draggedEle.grabbed() ){\n              r.dragData.didDrag = true;\n              var dPos = draggedEle._private.position;\n              var updatePos = !draggedEle.isParent();\n\n              if( updatePos && is.number(disp[0]) && is.number(disp[1]) ){\n                dPos.x += disp[0];\n                dPos.y += disp[1];\n              }\n\n              if( justStartedDrag ){\n                r.redrawHint('eles', true);\n\n                var dragDelta = r.touchData.dragDelta;\n\n                if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){\n                  dPos.x += dragDelta[0];\n                  dPos.y += dragDelta[1];\n                }\n\n              }\n            }\n          }\n\n          var tcol = Collection(cy, draggedEles);\n\n          tcol.updateCompoundBounds();\n          tcol.trigger('position drag');\n\n          r.hoverData.draggingEles = true;\n\n          r.redrawHint('drag', true);\n\n          if(\n               r.touchData.startPosition[0] == earlier[0]\n            && r.touchData.startPosition[1] == earlier[1]\n          ){\n\n            r.redrawHint('eles', true);\n          }\n\n          r.redraw();\n        } else { // otherise keep track of drag delta for later\n          var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || [];\n\n          if( dragDelta.length === 0 ){\n            dragDelta.push( disp[0] );\n            dragDelta.push( disp[1] );\n          } else {\n            dragDelta[0] += disp[0];\n            dragDelta[1] += disp[1];\n          }\n        }\n      }\n\n      // touchmove\n      {\n        triggerEvents( (start || near), ['touchmove', 'tapdrag', 'vmousemove'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n\n        if (near != last) {\n          if (last) { last.trigger(Event(e, { type: 'tapdragout', cyPosition: { x: now[0], y: now[1] } })); }\n          if (near) { near.trigger(Event(e, { type: 'tapdragover', cyPosition: { x: now[0], y: now[1] } })); }\n        }\n\n        r.touchData.last = near;\n      }\n\n      // check to cancel taphold\n      for (var i=0;i<now.length;i++) {\n        if( now[i]\n          && r.touchData.startPosition[i]\n          && rdist2 > r.touchTapThreshold2 ){\n\n          r.touchData.singleTouchMoved = true;\n        }\n      }\n\n      // panning\n      if(\n          capture\n          && ( start == null || start.isEdge() )\n          && cy.panningEnabled() && cy.userPanningEnabled()\n      ){\n\n        e.preventDefault();\n\n        if( r.swipePanning ){\n          cy.panBy({\n            x: disp[0] * zoom,\n            y: disp[1] * zoom\n          });\n\n        } else if( rdist2 >= r.touchTapThreshold2 ){\n          r.swipePanning = true;\n\n          cy.panBy({\n            x: dx * zoom,\n            y: dy * zoom\n          });\n\n          if( start ){\n            start.unactivate();\n\n            if( !r.data.bgActivePosistion ){\n              r.data.bgActivePosistion = {\n                x: now[0],\n                y: now[1]\n              };\n            }\n\n            r.redrawHint('select', true);\n\n            r.touchData.start = null;\n          }\n        }\n\n        // Re-project\n        var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n        now[0] = pos[0]; now[1] = pos[1];\n      }\n    }\n\n    for (var j=0; j<now.length; j++) { earlier[j] = now[j]; }\n    //r.redraw();\n\n  }, false);\n\n  var touchcancelHandler;\n  r.registerBinding(window, 'touchcancel', touchcancelHandler = function(e) {\n    var start = r.touchData.start;\n\n    r.touchData.capture = false;\n\n    if( start ){\n      start.unactivate();\n    }\n  });\n\n  var touchendHandler;\n  r.registerBinding(window, 'touchend', touchendHandler = function(e) {\n    var start = r.touchData.start;\n\n    var capture = r.touchData.capture;\n\n    if( capture ){\n      r.touchData.capture = false;\n\n      e.preventDefault();\n    } else {\n      return;\n    }\n\n    var select = r.selection;\n\n    r.swipePanning = false;\n    r.hoverData.draggingEles = false;\n\n    var cy = r.cy;\n    var zoom = cy.zoom();\n    var now = r.touchData.now;\n    var earlier = r.touchData.earlier;\n\n    if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n    if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n    if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n    if( start ){\n      start.unactivate();\n    }\n\n    var ctxTapend;\n    if( r.touchData.cxt ){\n      ctxTapend = Event(e, {\n        type: 'cxttapend',\n        cyPosition: { x: now[0], y: now[1] }\n      });\n\n      if( start ){\n        start.trigger( ctxTapend );\n      } else {\n        cy.trigger( ctxTapend );\n      }\n\n      if( !r.touchData.cxtDragged ){\n        var ctxTap = Event(e, {\n          type: 'cxttap',\n          cyPosition: { x: now[0], y: now[1] }\n        });\n\n        if( start ){\n          start.trigger( ctxTap );\n        } else {\n          cy.trigger( ctxTap );\n        }\n\n      }\n\n      if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n      r.touchData.cxt = false;\n      r.touchData.start = null;\n\n      r.redraw();\n      return;\n    }\n\n    // no more box selection if we don't have three fingers\n    if( !e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting ){\n      r.touchData.selecting = false;\n\n      var newlySelected = [];\n      var box = r.getAllInBox( select[0], select[1], select[2], select[3] );\n\n      select[0] = undefined;\n      select[1] = undefined;\n      select[2] = undefined;\n      select[3] = undefined;\n      select[4] = 0;\n\n      r.redrawHint('select', true);\n\n      for( var i = 0; i< box.length; i++ ) {\n        if( box[i]._private.selectable ){\n          newlySelected.push( box[i] );\n        }\n      }\n\n      var newlySelCol = Collection( cy, newlySelected );\n\n      newlySelCol.select();\n\n      if( newlySelCol.length > 0 ) {\n        r.redrawHint('eles', true);\n      } else {\n        r.redraw();\n      }\n    }\n\n    var updateStartStyle = false;\n\n    if( start != null ){\n      start._private.active = false;\n      updateStartStyle = true;\n      start.unactivate();\n    }\n\n    if (e.touches[2]) {\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n    } else if (e.touches[1]) {\n\n    } else if (e.touches[0]) {\n\n    // Last touch released\n    } else if (!e.touches[0]) {\n\n      r.data.bgActivePosistion = undefined;\n      r.redrawHint('select', true);\n\n      var draggedEles = r.dragData.touchDragEles;\n\n      if (start != null ) {\n\n        var startWasGrabbed = start._private.grabbed;\n\n        freeDraggedElements( draggedEles );\n\n        r.redrawHint('drag', true);\n        r.redrawHint('eles', true);\n\n        if( startWasGrabbed ){\n          start.trigger('free');\n        }\n\n        triggerEvents( start, ['touchend', 'tapend', 'vmouseup'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n\n        start.unactivate();\n\n        r.touchData.start = null;\n\n      } else {\n        var near = r.findNearestElement(now[0], now[1], true, true);\n\n        triggerEvents( near, ['touchend', 'tapend', 'vmouseup'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n\n      }\n\n      var dx = r.touchData.startPosition[0] - now[0];\n      var dx2 = dx * dx;\n      var dy = r.touchData.startPosition[1] - now[1];\n      var dy2 = dy * dy;\n      var dist2 = dx2 + dy2;\n      var rdist2 = dist2 * zoom * zoom;\n\n      // Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance\n      if (start != null\n          && !r.dragData.didDrag // didn't drag nodes around\n          && start._private.selectable\n          && rdist2 < r.touchTapThreshold2\n          && !r.pinching // pinch to zoom should not affect selection\n      ) {\n\n        if( cy.selectionType() === 'single' ){\n          cy.$(':selected').unmerge( start ).unselect();\n          start.select();\n        } else {\n          if( start.selected() ){\n            start.unselect();\n          } else {\n            start.select();\n          }\n        }\n\n        updateStartStyle = true;\n\n\n        r.redrawHint('eles', true);\n      }\n\n      // Tap event, roughly same as mouse click event for touch\n      if( !r.touchData.singleTouchMoved ){\n        triggerEvents( start, ['tap', 'vclick'], e, {\n          cyPosition: { x: now[0], y: now[1] }\n        } );\n      }\n\n      r.touchData.singleTouchMoved = true;\n    }\n\n    for( var j = 0; j < now.length; j++ ){ earlier[j] = now[j]; }\n\n    r.dragData.didDrag = false; // reset for next mousedown\n\n    if( e.touches.length === 0 ){\n      r.touchData.dragDelta = [];\n    }\n\n    if( updateStartStyle && start ){\n      start.updateStyle(false);\n    }\n\n    if( e.touches.length < 2 ){\n      r.pinching = false;\n      r.redrawHint('eles', true);\n      r.redraw();\n    }\n\n    //r.redraw();\n\n  }, false);\n\n  // fallback compatibility layer for ms pointer events\n  if( typeof TouchEvent === 'undefined' ){\n\n    var pointers = [];\n\n    var makeTouch = function( e ){\n      return {\n        clientX: e.clientX,\n        clientY: e.clientY,\n        force: 1,\n        identifier: e.pointerId,\n        pageX: e.pageX,\n        pageY: e.pageY,\n        radiusX: e.width/2,\n        radiusY: e.height/2,\n        screenX: e.screenX,\n        screenY: e.screenY,\n        target: e.target\n      };\n    };\n\n    var makePointer = function( e ){\n      return {\n        event: e,\n        touch: makeTouch(e)\n      };\n    };\n\n    var addPointer = function( e ){\n      pointers.push( makePointer(e) );\n    };\n\n    var removePointer = function( e ){\n      for( var i = 0; i < pointers.length; i++ ){\n        var p = pointers[i];\n\n        if( p.event.pointerId === e.pointerId ){\n          pointers.splice( i, 1 );\n          return;\n        }\n      }\n    };\n\n    var updatePointer = function( e ){\n      var p = pointers.filter(function( p ){\n        return p.event.pointerId === e.pointerId;\n      })[0];\n\n      p.event = e;\n      p.touch = makeTouch(e);\n    };\n\n    var addTouchesToEvent = function( e ){\n      e.touches = pointers.map(function( p ){\n        return p.touch;\n      });\n    };\n\n    r.registerBinding(r.container, 'pointerdown', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      e.preventDefault();\n\n      addPointer( e );\n\n      addTouchesToEvent( e );\n      touchstartHandler( e );\n    });\n\n    r.registerBinding(r.container, 'pointerup', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      removePointer( e );\n\n      addTouchesToEvent( e );\n      touchendHandler( e );\n    });\n\n    r.registerBinding(r.container, 'pointercancel', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      removePointer( e );\n\n      addTouchesToEvent( e );\n      touchcancelHandler( e );\n    });\n\n    r.registerBinding(r.container, 'pointermove', function(e){\n      if( e.pointerType === 'mouse' ){ return; } // mouse already handled\n\n      e.preventDefault();\n\n      updatePointer( e );\n\n      addTouchesToEvent( e );\n      touchmoveHandler( e );\n    });\n\n  }\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar math = require('../../../math');\n\nvar BRp = {};\n\nBRp.registerNodeShapes = function(){\n  var nodeShapes = this.nodeShapes = {};\n  var renderer = this;\n\n  nodeShapes['ellipse'] = {\n    name: 'ellipse',\n\n    draw: function( context, centerX, centerY, width, height ){\n      renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );\n    },\n\n    intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n      return math.intersectLineEllipse(\n        x, y,\n        nodeX,\n        nodeY,\n        width / 2 + padding,\n        height / 2 + padding)\n      ;\n    },\n\n    checkPoint: function( x, y, padding, width, height, centerX, centerY ){\n      x -= centerX;\n      y -= centerY;\n\n      x /= (width / 2 + padding);\n      y /= (height / 2 + padding);\n\n      return x*x + y*y <= 1;\n    }\n  };\n\n  function generatePolygon( name, points ){\n    return ( nodeShapes[name] = {\n      name: name,\n\n      points: points,\n\n      draw: function( context, centerX, centerY, width, height ){\n        renderer.nodeShapeImpl('polygon')( context, centerX, centerY, width, height, this.points );\n      },\n\n      intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n        return math.polygonIntersectLine(\n            x, y,\n            this.points,\n            nodeX,\n            nodeY,\n            width / 2, height / 2,\n            padding)\n          ;\n      },\n\n      checkPoint: function( x, y, padding, width, height, centerX, centerY ){\n        return math.pointInsidePolygon(x, y, nodeShapes[name].points,\n          centerX, centerY, width, height, [0, -1], padding)\n        ;\n      }\n    } );\n  }\n\n  generatePolygon( 'triangle', math.generateUnitNgonPointsFitToSquare(3, 0) );\n\n  generatePolygon( 'square', math.generateUnitNgonPointsFitToSquare(4, 0) );\n  nodeShapes['rectangle'] = nodeShapes['square'];\n\n  nodeShapes['roundrectangle'] = {\n    name: 'roundrectangle',\n\n    points: math.generateUnitNgonPointsFitToSquare(4, 0),\n\n    draw: function( context, centerX, centerY, width, height ){\n      renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );\n    },\n\n    intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n      return math.roundRectangleIntersectLine(\n        x, y,\n        nodeX,\n        nodeY,\n        width, height,\n        padding)\n      ;\n    },\n\n    // Looks like the width passed into this function is actually the total width / 2\n    checkPoint: function(\n      x, y, padding, width, height, centerX, centerY ){\n\n      var cornerRadius = math.getRoundRectangleRadius(width, height);\n\n      // Check hBox\n      if (math.pointInsidePolygon(x, y, this.points,\n        centerX, centerY, width, height - 2 * cornerRadius, [0, -1], padding) ){\n        return true;\n      }\n\n      // Check vBox\n      if (math.pointInsidePolygon(x, y, this.points,\n        centerX, centerY, width - 2 * cornerRadius, height, [0, -1], padding) ){\n        return true;\n      }\n\n      var checkInEllipse = function( x, y, centerX, centerY, width, height, padding ){\n        x -= centerX;\n        y -= centerY;\n\n        x /= (width / 2 + padding);\n        y /= (height / 2 + padding);\n\n        return (x*x + y*y <= 1);\n      };\n\n\n      // Check top left quarter circle\n      if (checkInEllipse(x, y,\n        centerX - width / 2 + cornerRadius,\n        centerY - height / 2 + cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      // Check top right quarter circle\n      if (checkInEllipse(x, y,\n        centerX + width / 2 - cornerRadius,\n        centerY - height / 2 + cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      // Check bottom right quarter circle\n      if (checkInEllipse(x, y,\n        centerX + width / 2 - cornerRadius,\n        centerY + height / 2 - cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      // Check bottom left quarter circle\n      if (checkInEllipse(x, y,\n        centerX - width / 2 + cornerRadius,\n        centerY + height / 2 - cornerRadius,\n        cornerRadius * 2, cornerRadius * 2, padding) ){\n\n        return true;\n      }\n\n      return false;\n    }\n  };\n\n  generatePolygon( 'diamond', [\n    0, 1,\n    1, 0,\n    0, -1,\n    -1, 0\n  ] );\n\n  generatePolygon( 'pentagon', math.generateUnitNgonPointsFitToSquare(5, 0) );\n\n  generatePolygon( 'hexagon', math.generateUnitNgonPointsFitToSquare(6, 0) );\n\n  generatePolygon( 'heptagon', math.generateUnitNgonPointsFitToSquare(7, 0) );\n\n  generatePolygon( 'octagon', math.generateUnitNgonPointsFitToSquare(8, 0) );\n\n  var star5Points = new Array(20);\n  {\n    var outerPoints = math.generateUnitNgonPoints(5, 0);\n    var innerPoints = math.generateUnitNgonPoints(5, Math.PI / 5);\n\n    // Outer radius is 1; inner radius of star is smaller\n    var innerRadius = 0.5 * (3 - Math.sqrt(5));\n    innerRadius *= 1.57;\n\n    for (var i=0;i<innerPoints.length/2;i++ ){\n      innerPoints[i*2] *= innerRadius;\n      innerPoints[i*2+1] *= innerRadius;\n    }\n\n    for (var i=0;i<20/4;i++ ){\n      star5Points[i*4] = outerPoints[i*2];\n      star5Points[i*4+1] = outerPoints[i*2+1];\n\n      star5Points[i*4+2] = innerPoints[i*2];\n      star5Points[i*4+3] = innerPoints[i*2+1];\n    }\n  }\n\n  star5Points = math.fitPolygonToSquare( star5Points );\n\n  generatePolygon( 'star', star5Points );\n\n  generatePolygon( 'vee', [\n    -1, -1,\n    0, -0.333,\n    1, -1,\n    0, 1\n  ] );\n\n  generatePolygon( 'rhomboid', [\n    -1, -1,\n    0.333, -1,\n    1, 1,\n    -0.333, 1\n  ] );\n\n  nodeShapes.makePolygon = function( points ){\n\n    // use caching on user-specified polygons so they are as fast as native shapes\n\n    var key = points.join('$');\n    var name = 'polygon-' + key;\n    var shape;\n\n    if( (shape = nodeShapes[name]) ){ // got cached shape\n      return shape;\n    }\n\n    // create and cache new shape\n    return generatePolygon( name, points );\n  };\n\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar util = require('../../../util');\n\nvar BRp = {};\n\nBRp.timeToRender = function(){\n  return this.redrawTotalTime / this.redrawCount;\n};\n\nvar minRedrawLimit = 1000/60; // people can't see much better than 60fps\nvar maxRedrawLimit = 1000;  // don't cap max b/c it's more important to be responsive than smooth\n\nBRp.redraw = function( options ){\n  options = options || util.staticEmptyObject();\n\n  var r = this;\n  var forcedContext = options.forcedContext;\n\n  if( r.averageRedrawTime === undefined ){ r.averageRedrawTime = 0; }\n  if( r.lastRedrawTime === undefined ){ r.lastRedrawTime = 0; }\n\n  var redrawLimit = r.lastRedrawTime; // estimate the ideal redraw limit based on how fast we can draw\n  redrawLimit = minRedrawLimit > redrawLimit ? minRedrawLimit : redrawLimit;\n  redrawLimit = redrawLimit < maxRedrawLimit ? redrawLimit : maxRedrawLimit;\n\n  if( r.lastDrawTime === undefined ){ r.lastDrawTime = 0; }\n\n  var nowTime = Date.now();\n  var timeElapsed = nowTime - r.lastDrawTime;\n  var callAfterLimit = timeElapsed >= redrawLimit;\n\n  if( !forcedContext ){\n    if( !callAfterLimit || r.currentlyDrawing ){\n      r.skipFrame = true;\n      return;\n    }\n  }\n\n  r.requestedFrame = true;\n  r.currentlyDrawing = true;\n  r.renderOptions = options;\n};\n\nBRp.startRenderLoop = function(){\n  var r = this;\n\n  var renderFn = function(){\n    if( r.destroyed ){ return; }\n\n    if( r.requestedFrame && !r.skipFrame ){\n      var startTime = util.performanceNow();\n\n      r.render( r.renderOptions );\n\n      var endTime = r.lastRedrawTime = util.performanceNow();\n\n      if( r.averageRedrawTime === undefined ){\n        r.averageRedrawTime = endTime - startTime;\n      }\n\n      if( r.redrawCount === undefined ){\n        r.redrawCount = 0;\n      }\n\n      r.redrawCount++;\n\n      if( r.redrawTotalTime === undefined ){\n        r.redrawTotalTime = 0;\n      }\n\n      var duration = endTime - startTime;\n\n      r.redrawTotalTime += duration;\n      r.lastRedrawTime = duration;\n\n      // use a weighted average with a bias from the previous average so we don't spike so easily\n      r.averageRedrawTime = r.averageRedrawTime/2 + duration/2;\n\n      r.requestedFrame = false;\n    }\n\n    r.skipFrame = false;\n\n    util.requestAnimationFrame( renderFn );\n  };\n\n  util.requestAnimationFrame( renderFn );\n\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar CRp = {};\n\nvar impl;\n\nCRp.arrowShapeImpl = function( name ){\n  return ( impl || (impl = {\n    'polygon': function( context, points ){\n      for( var i = 0; i < points.length; i++ ){\n        var pt = points[i];\n\n        context.lineTo( pt.x, pt.y );\n      }\n    },\n\n    'triangle-backcurve': function( context, points, controlPoint ){\n      var firstPt;\n\n      for( var i = 0; i < points.length; i++ ){\n        var pt = points[i];\n\n        if( i === 0 ){\n          firstPt = pt;\n        }\n\n        context.lineTo( pt.x, pt.y );\n      }\n\n      context.quadraticCurveTo( controlPoint.x, controlPoint.y, firstPt.x, firstPt.y );\n    },\n\n    'triangle-tee': function( context, trianglePoints, teePoints ){\n      var triPts = trianglePoints;\n      for( var i = 0; i < triPts.length; i++ ){\n        var pt = triPts[i];\n\n        context.lineTo( pt.x, pt.y );\n      }\n\n      var teePts = teePoints;\n      var firstTeePt = teePoints[0];\n      context.moveTo( firstTeePt.x, firstTeePt.y );\n\n      for( var i = 0; i < teePts.length; i++ ){\n        var pt = teePts[i];\n\n        context.lineTo( pt.x, pt.y );\n      }\n    },\n\n    'circle': function( context, rx, ry, r ){\n      context.arc(rx, ry, r, 0, Math.PI * 2, false);\n    }\n  }) )[ name ];\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nvar CRp = {};\n\nCRp.drawEdge = function(context, edge, drawOverlayInstead) {\n  var rs = edge._private.rscratch;\n  var usePaths = this.usePaths();\n\n  // if bezier ctrl pts can not be calculated, then die\n  if( rs.badBezier || rs.badLine || isNaN( rs.allpts[0] ) ){ // iNaN in case edge is impossible and browser bugs (e.g. safari)\n    return;\n  }\n\n  var style = edge._private.style;\n\n  // Edge line width\n  if (style['width'].pfValue <= 0) {\n    return;\n  }\n\n  var overlayPadding = style['overlay-padding'].pfValue;\n  var overlayOpacity = style['overlay-opacity'].value;\n  var overlayColor = style['overlay-color'].value;\n\n  // Edge color & opacity\n  if( drawOverlayInstead ){\n\n    if( overlayOpacity === 0 ){ // exit early if no overlay\n      return;\n    }\n\n    this.strokeStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n    context.lineCap = 'round';\n\n    if( rs.edgeType == 'self' && !usePaths ){\n      context.lineCap = 'butt';\n    }\n\n  } else {\n    var lineColor = style['line-color'].value;\n\n    this.strokeStyle(context, lineColor[0], lineColor[1], lineColor[2], style.opacity.value);\n\n    context.lineCap = 'butt';\n  }\n\n  var edgeWidth = style['width'].pfValue + (drawOverlayInstead ? 2 * overlayPadding : 0);\n  var lineStyle = drawOverlayInstead ? 'solid' : style['line-style'].value;\n  context.lineWidth = edgeWidth;\n\n  var shadowBlur = style['shadow-blur'].pfValue;\n  var shadowOpacity = style['shadow-opacity'].value;\n  var shadowColor = style['shadow-color'].value;\n  var shadowOffsetX = style['shadow-offset-x'].pfValue;\n  var shadowOffsetY = style['shadow-offset-y'].pfValue;\n\n  this.shadowStyle(context,  shadowColor, drawOverlayInstead ? 0 : shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n  this.drawEdgePath(\n    edge,\n    context,\n    rs.allpts,\n    lineStyle,\n    edgeWidth\n  );\n\n  this.drawArrowheads(context, edge, drawOverlayInstead);\n\n  this.shadowStyle(context, 'transparent', 0); // reset for next guy\n\n};\n\n\nCRp.drawEdgePath = function(edge, context, pts, type, width) {\n  var rs = edge._private.rscratch;\n  var canvasCxt = context;\n  var path;\n  var pathCacheHit = false;\n  var usePaths = this.usePaths();\n\n  if( usePaths ){\n    var pathCacheKey = pts.join('$');\n    var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey;\n\n    if( keyMatches ){\n      path = context = rs.pathCache;\n      pathCacheHit = true;\n    } else {\n      path = context = new Path2D();\n      rs.pathCacheKey = pathCacheKey;\n      rs.pathCache = path;\n    }\n  }\n\n  if( canvasCxt.setLineDash ){ // for very outofdate browsers\n    switch( type ){\n      case 'dotted':\n        canvasCxt.setLineDash([ 1, 1 ]);\n        break;\n\n      case 'dashed':\n        canvasCxt.setLineDash([ 6, 3 ]);\n        break;\n\n      case 'solid':\n        canvasCxt.setLineDash([ ]);\n        break;\n    }\n  }\n\n  if( !pathCacheHit ){\n    if( context.beginPath ){ context.beginPath(); }\n    context.moveTo( pts[0], pts[1] );\n\n    switch( rs.edgeType ){\n      case 'bezier':\n      case 'self':\n      case 'compound':\n      case 'multibezier':\n        if( !rs.badBezier ){\n          for( var i = 2; i + 3 < pts.length; i += 4 ){\n            context.quadraticCurveTo( pts[i], pts[i+1], pts[i+2], pts[i+3] );\n          }\n        }\n        break;\n\n      case 'straight':\n      case 'segments':\n      case 'haystack':\n        if( !rs.badLine ){\n          for( var i = 2; i + 1 < pts.length; i += 2 ){\n            context.lineTo( pts[i], pts[i+1] );\n          }\n        }\n        break;\n    }\n  }\n\n  context = canvasCxt;\n  if( usePaths ){\n    context.stroke( path );\n  } else {\n    context.stroke();\n  }\n\n  // reset any line dashes\n  if( context.setLineDash ){ // for very outofdate browsers\n    context.setLineDash([ ]);\n  }\n\n};\n\nCRp.drawArrowheads = function(context, edge, drawOverlayInstead) {\n  if( drawOverlayInstead ){ return; } // don't do anything for overlays\n\n  var rs = edge._private.rscratch;\n  var isHaystack = rs.edgeType === 'haystack';\n\n  if( !isHaystack ){\n    this.drawArrowhead( context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle );\n  }\n\n  this.drawArrowhead( context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle );\n\n  this.drawArrowhead( context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle );\n\n  if( !isHaystack ){\n    this.drawArrowhead( context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle );\n  }\n};\n\nCRp.drawArrowhead = function( context, edge, prefix, x, y, angle ){\n  if( isNaN(x) || x == null || isNaN(y) || y == null || isNaN(angle) || angle == null ){ return; }\n\n  var self = this;\n  var style = edge._private.style;\n  var arrowShape = style[prefix + '-arrow-shape'].value;\n\n  if( arrowShape === 'none' ){\n    return;\n  }\n\n  var gco = context.globalCompositeOperation;\n\n  var arrowClearFill = style[prefix + '-arrow-fill'].value === 'hollow' ? 'both' : 'filled';\n  var arrowFill = style[prefix + '-arrow-fill'].value;\n\n  if( arrowShape === 'half-triangle-overshot' ){\n    arrowFill = 'hollow';\n    arrowClearFill = 'hollow';\n  }\n\n  if( style.opacity.value !== 1 || arrowFill === 'hollow' ){ // then extra clear is needed\n    context.globalCompositeOperation = 'destination-out';\n\n    self.fillStyle(context, 255, 255, 255, 1);\n    self.strokeStyle(context, 255, 255, 255, 1);\n\n    self.drawArrowShape( edge, prefix, context,\n      arrowClearFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,\n      x, y, angle\n    );\n\n    context.globalCompositeOperation = gco;\n  } // otherwise, the opaque arrow clears it for free :)\n\n  var color = style[prefix + '-arrow-color'].value;\n  self.fillStyle(context, color[0], color[1], color[2], style.opacity.value);\n  self.strokeStyle(context, color[0], color[1], color[2], style.opacity.value);\n\n  self.drawArrowShape( edge, prefix, context,\n    arrowFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,\n    x, y, angle\n  );\n};\n\nCRp.drawArrowShape = function(edge, arrowType, context, fill, edgeWidth, shape, x, y, angle) {\n  var r = this;\n  var usePaths = this.usePaths();\n  var rs = edge._private.rscratch;\n  var pathCacheHit = false;\n  var path;\n  var canvasContext = context;\n  var translation = { x: x, y: y };\n  var size = this.getArrowWidth( edgeWidth );\n  var shapeImpl = r.arrowShapes[shape];\n\n  if( usePaths ){\n    var pathCacheKey = size + '$' + shape + '$' + angle + '$' + x + '$' + y;\n    rs.arrowPathCacheKey = rs.arrowPathCacheKey || {};\n    rs.arrowPathCache = rs.arrowPathCache || {};\n\n    var alreadyCached = rs.arrowPathCacheKey[arrowType] === pathCacheKey;\n    if( alreadyCached ){\n      path = context = rs.arrowPathCache[arrowType];\n      pathCacheHit = true;\n    } else {\n      path = context = new Path2D();\n      rs.arrowPathCacheKey[arrowType] = pathCacheKey;\n      rs.arrowPathCache[arrowType] = path;\n    }\n  }\n\n  if( context.beginPath ){ context.beginPath(); }\n\n  if( !pathCacheHit ){\n    shapeImpl.draw(context, size, angle, translation);\n  }\n\n  if( !shapeImpl.leavePathOpen && context.closePath ){\n    context.closePath();\n  }\n\n  context = canvasContext;\n\n  if( fill === 'filled' || fill === 'both' ){\n    if( usePaths ){\n      context.fill( path );\n    } else {\n      context.fill();\n    }\n  }\n\n  if( fill === 'hollow' || fill === 'both' ){\n    context.lineWidth = ( shapeImpl.matchEdgeWidth ? edgeWidth : 1 );\n    context.lineJoin = 'miter';\n\n    if( usePaths ){\n      context.stroke( path );\n    } else {\n      context.stroke();\n    }\n\n  }\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nvar CRp = {};\n\nCRp.safeDrawImage = function( context, img, ix, iy, iw, ih, x, y, w, h ){\n  var r = this;\n\n  try {\n    context.drawImage( img, ix, iy, iw, ih, x, y, w, h );\n  } catch(e){\n    r.data.canvasNeedsRedraw[r.NODE] = true;\n    r.data.canvasNeedsRedraw[r.DRAG] = true;\n\n    r.drawingImage = true;\n\n    r.redraw();\n  }\n};\n\nCRp.drawInscribedImage = function(context, img, node) {\n  var r = this;\n  var nodeX = node._private.position.x;\n  var nodeY = node._private.position.y;\n  var style = node._private.style;\n  var fit = style['background-fit'].value;\n  var xPos = style['background-position-x'];\n  var yPos = style['background-position-y'];\n  var repeat = style['background-repeat'].value;\n  var nodeW = node.width();\n  var nodeH = node.height();\n  var rs = node._private.rscratch;\n  var clip = style['background-clip'].value;\n  var shouldClip = clip === 'node';\n  var imgOpacity = style['background-image-opacity'].value;\n\n  var imgW = img.width || img.cachedW;\n  var imgH = img.height || img.cachedH;\n\n  // workaround for broken browsers like ie\n  if( null == imgW || null == imgH ){\n    document.body.appendChild( img );\n\n    imgW = img.cachedW = img.width || img.offsetWidth;\n    imgH = img.cachedH = img.height || img.offsetHeight;\n\n    document.body.removeChild( img );\n  }\n\n  var w = imgW;\n  var h = imgH;\n\n  var bgW = style['background-width'];\n  if( bgW.value !== 'auto' ){\n    if( bgW.units === '%' ){\n      w = bgW.value/100 * nodeW;\n    } else {\n      w = bgW.pfValue;\n    }\n  }\n\n  var bgH = style['background-height'];\n  if( bgH.value !== 'auto' ){\n    if( bgH.units === '%' ){\n      h = bgH.value/100 * nodeH;\n    } else {\n      h = bgH.pfValue;\n    }\n  }\n\n  if( w === 0 || h === 0 ){\n    return; // no point in drawing empty image (and chrome is broken in this case)\n  }\n\n  if( fit === 'contain' ){\n    var scale = Math.min( nodeW/w, nodeH/h );\n\n    w *= scale;\n    h *= scale;\n\n  } else if( fit === 'cover' ){\n    var scale = Math.max( nodeW/w, nodeH/h );\n\n    w *= scale;\n    h *= scale;\n  }\n\n  var x = (nodeX - nodeW/2); // left\n  if( xPos.units === '%' ){\n    x += (nodeW - w) * xPos.value/100;\n  } else {\n    x += xPos.pfValue;\n  }\n\n  var y = (nodeY - nodeH/2); // top\n  if( yPos.units === '%' ){\n    y += (nodeH - h) * yPos.value/100;\n  } else {\n    y += yPos.pfValue;\n  }\n\n  if( rs.pathCache ){\n    x -= nodeX;\n    y -= nodeY;\n\n    nodeX = 0;\n    nodeY = 0;\n  }\n\n  var gAlpha = context.globalAlpha;\n\n  context.globalAlpha = imgOpacity;\n\n  if( repeat === 'no-repeat' ){\n\n    if( shouldClip ){\n      context.save();\n\n      if( rs.pathCache ){\n        context.clip( rs.pathCache );\n      } else {\n        r.nodeShapes[r.getNodeShape(node)].draw(\n          context,\n          nodeX, nodeY,\n          nodeW, nodeH);\n\n        context.clip();\n      }\n    }\n\n    r.safeDrawImage( context, img, 0, 0, imgW, imgH, x, y, w, h );\n\n    if( shouldClip ){\n      context.restore();\n    }\n  } else {\n    var pattern = context.createPattern( img, repeat );\n    context.fillStyle = pattern;\n\n    r.nodeShapes[r.getNodeShape(node)].draw(\n        context,\n        nodeX, nodeY,\n        nodeW, nodeH);\n\n      context.translate(x, y);\n      context.fill();\n      context.translate(-x, -y);\n  }\n\n  context.globalAlpha = gAlpha;\n\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nvar is = require('../../../is');\n\nvar CRp = {};\n\n// Draw edge text\nCRp.drawEdgeText = function(context, edge) {\n  var text = edge._private.style['label'].strValue;\n\n  if( !text || text.match(/^\\s+$/) ){\n    return;\n  }\n\n  if( this.hideEdgesOnViewport && (this.dragData.didDrag || this.pinching || this.hoverData.dragging || this.data.wheel || this.swipePanning) ){ return; } // save cycles on pinching\n\n  var computedSize = edge._private.style['font-size'].pfValue * edge.cy().zoom();\n  var minSize = edge._private.style['min-zoomed-font-size'].pfValue;\n\n  if( computedSize < minSize ){\n    return;\n  }\n\n  // Calculate text draw position\n\n  context.textAlign = 'center';\n  context.textBaseline = 'middle';\n\n  var rs = edge._private.rscratch;\n  if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered\n\n  var style = edge._private.style;\n  var autorotate = style['edge-text-rotation'].strValue === 'autorotate';\n  var theta;\n\n  if( autorotate ){\n    theta = rs.labelAngle;\n\n    context.translate(rs.labelX, rs.labelY);\n    context.rotate(theta);\n\n    this.drawText(context, edge, 0, 0);\n\n    context.rotate(-theta);\n    context.translate(-rs.labelX, -rs.labelY);\n  } else {\n    this.drawText(context, edge, rs.labelX, rs.labelY);\n  }\n\n};\n\n// Draw node text\nCRp.drawNodeText = function(context, node) {\n  var text = node._private.style['label'].strValue;\n\n  if ( !text || text.match(/^\\s+$/) ) {\n    return;\n  }\n\n  var computedSize = node._private.style['font-size'].pfValue * node.cy().zoom();\n  var minSize = node._private.style['min-zoomed-font-size'].pfValue;\n\n  if( computedSize < minSize ){\n    return;\n  }\n\n  // this.recalculateNodeLabelProjection( node );\n\n  var textHalign = node._private.style['text-halign'].strValue;\n  var textValign = node._private.style['text-valign'].strValue;\n  var rs = node._private.rscratch;\n  if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered\n\n  switch( textHalign ){\n    case 'left':\n      context.textAlign = 'right';\n      break;\n\n    case 'right':\n      context.textAlign = 'left';\n      break;\n\n    default: // e.g. center\n      context.textAlign = 'center';\n  }\n\n  switch( textValign ){\n    case 'top':\n      context.textBaseline = 'bottom';\n      break;\n\n    case 'bottom':\n      context.textBaseline = 'top';\n      break;\n\n    default: // e.g. center\n      context.textBaseline = 'middle';\n  }\n\n  this.drawText(context, node, rs.labelX, rs.labelY);\n};\n\nCRp.getFontCache = function(context){\n  var cache;\n\n  this.fontCaches = this.fontCaches || [];\n\n  for( var i = 0; i < this.fontCaches.length; i++ ){\n    cache = this.fontCaches[i];\n\n    if( cache.context === context ){\n      return cache;\n    }\n  }\n\n  cache = {\n    context: context\n  };\n  this.fontCaches.push(cache);\n\n  return cache;\n};\n\n// set up canvas context with font\n// returns transformed text string\nCRp.setupTextStyle = function( context, element ){\n  // Font style\n  var parentOpacity = element.effectiveOpacity();\n  var style = element._private.style;\n  var labelStyle = style['font-style'].strValue;\n  var labelSize = style['font-size'].pfValue + 'px';\n  var labelFamily = style['font-family'].strValue;\n  var labelWeight = style['font-weight'].strValue;\n  var opacity = style['text-opacity'].value * style['opacity'].value * parentOpacity;\n  var outlineOpacity = style['text-outline-opacity'].value * opacity;\n  var color = style['color'].value;\n  var outlineColor = style['text-outline-color'].value;\n  var shadowBlur = style['text-shadow-blur'].pfValue;\n  var shadowOpacity = style['text-shadow-opacity'].value;\n  var shadowColor = style['text-shadow-color'].value;\n  var shadowOffsetX = style['text-shadow-offset-x'].pfValue;\n  var shadowOffsetY = style['text-shadow-offset-y'].pfValue;\n\n  var fontCacheKey = element._private.fontKey;\n  var cache = this.getFontCache(context);\n\n  if( cache.key !== fontCacheKey ){\n    context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily;\n\n    cache.key = fontCacheKey;\n  }\n\n  var text = this.getLabelText( element );\n\n  // Calculate text draw position based on text alignment\n\n  // so text outlines aren't jagged\n  context.lineJoin = 'round';\n\n  this.fillStyle(context, color[0], color[1], color[2], opacity);\n\n  this.strokeStyle(context, outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity);\n\n  this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n  return text;\n};\n\nfunction roundRect(ctx, x, y, width, height, radius) {\n  var radius = radius || 5;\n  ctx.beginPath();\n  ctx.moveTo(x + radius, y);\n  ctx.lineTo(x + width - radius, y);\n  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n  ctx.lineTo(x + width, y + height - radius);\n  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n  ctx.lineTo(x + radius, y + height);\n  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n  ctx.lineTo(x, y + radius);\n  ctx.quadraticCurveTo(x, y, x + radius, y);\n  ctx.closePath();\n  ctx.fill();\n}\n\n// Draw text\nCRp.drawText = function(context, element, textX, textY) {\n  var _p = element._private;\n  var style = _p.style;\n  var rstyle = _p.rstyle;\n  var rscratch = _p.rscratch;\n  var parentOpacity = element.effectiveOpacity();\n  if( parentOpacity === 0 || style['text-opacity'].value === 0){ return; }\n\n  var text = this.setupTextStyle( context, element );\n  var halign = style['text-halign'].value;\n  var valign = style['text-valign'].value;\n\n  if( element.isEdge() ){\n    halign = 'center';\n    valign = 'center';\n  }\n\n  if( element.isNode() ){\n    var pLeft = style['padding-left'].pfValue;\n    var pRight = style['padding-right'].pfValue;\n    var pTop = style['padding-top'].pfValue;\n    var pBottom = style['padding-bottom'].pfValue;\n\n    textX += pLeft/2;\n    textX -= pRight/2;\n\n    textY += pTop/2;\n    textY -= pBottom/2;\n  }\n\n  if ( text != null && !isNaN(textX) && !isNaN(textY)) {\n    var backgroundOpacity = style['text-background-opacity'].value;\n    var borderOpacity = style['text-border-opacity'].value;\n    var textBorderWidth = style['text-border-width'].pfValue;\n\n    if( backgroundOpacity > 0 || (textBorderWidth > 0 && borderOpacity > 0) ){\n      var margin = 4 + textBorderWidth/2;\n\n      if (element.isNode()) {\n        //Move textX, textY to include the background margins\n        if (valign === 'top') {\n          textY -= margin;\n        } else if (valign === 'bottom') {\n          textY += margin;\n        }\n        if (halign === 'left') {\n          textX -= margin;\n        } else if (halign === 'right') {\n          textX += margin;\n        }\n      }\n\n      var bgWidth = rstyle.labelWidth;\n      var bgHeight = rstyle.labelHeight;\n      var bgX = textX;\n\n      if (halign) {\n        if (halign == 'center') {\n          bgX = bgX - bgWidth / 2;\n        } else if (halign == 'left') {\n          bgX = bgX- bgWidth;\n        }\n      }\n\n      var bgY = textY;\n\n      if (element.isNode()) {\n        if (valign == 'top') {\n           bgY = bgY - bgHeight;\n        } else if (valign == 'center') {\n          bgY = bgY- bgHeight / 2;\n        }\n      } else {\n        bgY = bgY - bgHeight / 2;\n      }\n\n      if (style['edge-text-rotation'].strValue === 'autorotate') {\n        textY = 0;\n        bgWidth += 4;\n        bgX = textX - bgWidth / 2;\n        bgY = textY - bgHeight / 2;\n      } else {\n        // Adjust with border width & margin\n        bgX -= margin;\n        bgY -= margin;\n        bgHeight += margin*2;\n        bgWidth += margin*2;\n      }\n\n      if( backgroundOpacity > 0 ){\n        var textFill = context.fillStyle;\n        var textBackgroundColor = style['text-background-color'].value;\n\n        context.fillStyle = 'rgba(' + textBackgroundColor[0] + ',' + textBackgroundColor[1] + ',' + textBackgroundColor[2] + ',' + backgroundOpacity * parentOpacity + ')';\n        var styleShape = style['text-background-shape'].strValue;\n        if (styleShape == 'roundrectangle') {\n          roundRect(context, bgX, bgY, bgWidth, bgHeight, 2);\n        } else {\n          context.fillRect(bgX,bgY,bgWidth,bgHeight);\n        }\n        context.fillStyle = textFill;\n      }\n\n      if( textBorderWidth > 0 && borderOpacity > 0 ){\n        var textStroke = context.strokeStyle;\n        var textLineWidth = context.lineWidth;\n        var textBorderColor = style['text-border-color'].value;\n        var textBorderStyle = style['text-border-style'].value;\n\n        context.strokeStyle = 'rgba(' + textBorderColor[0] + ',' + textBorderColor[1] + ',' + textBorderColor[2] + ',' + borderOpacity * parentOpacity + ')';\n        context.lineWidth = textBorderWidth;\n\n        if( context.setLineDash ){ // for very outofdate browsers\n          switch( textBorderStyle ){\n            case 'dotted':\n              context.setLineDash([ 1, 1 ]);\n              break;\n            case 'dashed':\n              context.setLineDash([ 4, 2 ]);\n              break;\n            case 'double':\n              context.lineWidth = textBorderWidth/4; // 50% reserved for white between the two borders\n              context.setLineDash([ ]);\n              break;\n            case 'solid':\n              context.setLineDash([ ]);\n              break;\n          }\n        }\n\n        context.strokeRect(bgX,bgY,bgWidth,bgHeight);\n\n        if( textBorderStyle === 'double' ){\n          var whiteWidth = textBorderWidth/2;\n\n          context.strokeRect(bgX+whiteWidth,bgY+whiteWidth,bgWidth-whiteWidth*2,bgHeight-whiteWidth*2);\n        }\n\n        if( context.setLineDash ){ // for very outofdate browsers\n          context.setLineDash([ ]);\n        }\n        context.lineWidth = textLineWidth;\n        context.strokeStyle = textStroke;\n      }\n\n    }\n\n    var lineWidth = 2  * style['text-outline-width'].pfValue; // *2 b/c the stroke is drawn centred on the middle\n\n    if( lineWidth > 0 ){\n      context.lineWidth = lineWidth;\n    }\n\n    if( style['text-wrap'].value === 'wrap' ){\n      var lines = rscratch.labelWrapCachedLines;\n      var lineHeight = rstyle.labelHeight / lines.length;\n\n      switch( valign ){\n        case 'top':\n          textY -= (lines.length - 1) * lineHeight;\n          break;\n\n        case 'bottom':\n          // nothing required\n          break;\n\n        default:\n        case 'center':\n          textY -= (lines.length - 1) * lineHeight / 2;\n      }\n\n      for( var l = 0; l < lines.length; l++ ){\n        if( lineWidth > 0 ){\n          context.strokeText( lines[l], textX, textY );\n        }\n\n        context.fillText( lines[l], textX, textY );\n\n        textY += lineHeight;\n      }\n\n    } else {\n      if( lineWidth > 0 ){\n        context.strokeText( text, textX, textY );\n      }\n\n      context.fillText( text, textX, textY );\n    }\n\n\n    this.shadowStyle(context, 'transparent', 0); // reset for next guy\n  }\n};\n\n\nmodule.exports = CRp;\n","'use strict';\n\nvar is = require('../../../is');\n\nvar CRp = {};\n\n// Draw node\nCRp.drawNode = function(context, node, drawOverlayInstead) {\n\n  var r = this;\n  var nodeWidth, nodeHeight;\n  var style = node._private.style;\n  var rs = node._private.rscratch;\n  var _p = node._private;\n  var pos = _p.position;\n\n  if( !is.number(pos.x) || !is.number(pos.y) ){\n    return; // can't draw node with undefined position\n  }\n\n  var usePaths = this.usePaths();\n  var canvasContext = context;\n  var path;\n  var pathCacheHit = false;\n\n  var overlayPadding = style['overlay-padding'].pfValue;\n  var overlayOpacity = style['overlay-opacity'].value;\n  var overlayColor = style['overlay-color'].value;\n\n  if( drawOverlayInstead && overlayOpacity === 0 ){ // exit early if drawing overlay but none to draw\n    return;\n  }\n\n  var parentOpacity = node.effectiveOpacity();\n  if( parentOpacity === 0 ){ return; }\n\n  nodeWidth = node.width() + style['padding-left'].pfValue + style['padding-right'].pfValue;\n  nodeHeight = node.height() + style['padding-top'].pfValue + style['padding-bottom'].pfValue;\n\n  context.lineWidth = style['border-width'].pfValue;\n\n  if( drawOverlayInstead === undefined || !drawOverlayInstead ){\n\n    var url = style['background-image'].value[2] ||\n      style['background-image'].value[1];\n    var image;\n\n    if (url !== undefined) {\n\n      // get image, and if not loaded then ask to redraw when later loaded\n      image = this.getCachedImage(url, function(){\n        r.data.canvasNeedsRedraw[r.NODE] = true;\n        r.data.canvasNeedsRedraw[r.DRAG] = true;\n\n        r.drawingImage = true;\n\n        r.redraw();\n      });\n\n      var prevBging = _p.backgrounding;\n      _p.backgrounding = !image.complete;\n\n      if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed\n        node.updateStyle( false );\n      }\n    }\n\n    // Node color & opacity\n\n    var bgColor = style['background-color'].value;\n    var borderColor = style['border-color'].value;\n    var borderStyle = style['border-style'].value;\n\n    this.fillStyle(context, bgColor[0], bgColor[1], bgColor[2], style['background-opacity'].value * parentOpacity);\n\n    this.strokeStyle(context, borderColor[0], borderColor[1], borderColor[2], style['border-opacity'].value * parentOpacity);\n\n    var shadowBlur = style['shadow-blur'].pfValue;\n    var shadowOpacity = style['shadow-opacity'].value;\n    var shadowColor = style['shadow-color'].value;\n    var shadowOffsetX = style['shadow-offset-x'].pfValue;\n    var shadowOffsetY = style['shadow-offset-y'].pfValue;\n\n    this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n    context.lineJoin = 'miter'; // so borders are square with the node shape\n\n    if( context.setLineDash ){ // for very outofdate browsers\n      switch( borderStyle ){\n        case 'dotted':\n          context.setLineDash([ 1, 1 ]);\n          break;\n\n        case 'dashed':\n          context.setLineDash([ 4, 2 ]);\n          break;\n\n        case 'solid':\n        case 'double':\n          context.setLineDash([ ]);\n          break;\n      }\n    }\n\n\n    var styleShape = style['shape'].strValue;\n\n    if( usePaths ){\n      var pathCacheKey = styleShape + '$' + nodeWidth +'$' + nodeHeight;\n\n      context.translate( pos.x, pos.y );\n\n      if( rs.pathCacheKey === pathCacheKey ){\n        path = context = rs.pathCache;\n        pathCacheHit = true;\n      } else {\n        path = context = new Path2D();\n        rs.pathCacheKey = pathCacheKey;\n        rs.pathCache = path;\n      }\n    }\n\n    if( !pathCacheHit ){\n\n      var npos = pos;\n\n      if( usePaths ){\n        npos = {\n          x: 0,\n          y: 0\n        };\n      }\n\n      r.nodeShapes[this.getNodeShape(node)].draw(\n            context,\n            npos.x,\n            npos.y,\n            nodeWidth,\n            nodeHeight);\n    }\n\n    context = canvasContext;\n\n    if( usePaths ){\n      context.fill( path );\n    } else {\n      context.fill();\n    }\n\n    this.shadowStyle(context, 'transparent', 0); // reset for next guy\n\n    if (url !== undefined) {\n      if( image.complete ){\n        this.drawInscribedImage(context, image, node);\n      }\n    }\n\n    var darkness = style['background-blacken'].value;\n    var borderWidth = style['border-width'].pfValue;\n\n    if( this.hasPie(node) ){\n      this.drawPie( context, node, parentOpacity );\n\n      // redraw path for blacken and border\n      if( darkness !== 0 || borderWidth !== 0 ){\n\n        if( !usePaths ){\n          r.nodeShapes[this.getNodeShape(node)].draw(\n              context,\n              pos.x,\n              pos.y,\n              nodeWidth,\n              nodeHeight);\n        }\n      }\n    }\n\n    if( darkness > 0 ){\n      this.fillStyle(context, 0, 0, 0, darkness);\n\n      if( usePaths ){\n        context.fill( path );\n      } else {\n        context.fill();\n      }\n\n    } else if( darkness < 0 ){\n      this.fillStyle(context, 255, 255, 255, -darkness);\n\n      if( usePaths ){\n        context.fill( path );\n      } else {\n        context.fill();\n      }\n    }\n\n    // Border width, draw border\n    if (borderWidth > 0) {\n\n      if( usePaths ){\n        context.stroke( path );\n      } else {\n        context.stroke();\n      }\n\n      if( borderStyle === 'double' ){\n        context.lineWidth = style['border-width'].pfValue/3;\n\n        var gco = context.globalCompositeOperation;\n        context.globalCompositeOperation = 'destination-out';\n\n        if( usePaths ){\n          context.stroke( path );\n        } else {\n          context.stroke();\n        }\n\n        context.globalCompositeOperation = gco;\n      }\n\n    }\n\n    if( usePaths ){\n      context.translate( -pos.x, -pos.y );\n    }\n\n    // reset in case we changed the border style\n    if( context.setLineDash ){ // for very outofdate browsers\n      context.setLineDash([ ]);\n    }\n\n  // draw the overlay\n  } else {\n\n    if( overlayOpacity > 0 ){\n      this.fillStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n\n      r.nodeShapes['roundrectangle'].draw(\n        context,\n        node._private.position.x,\n        node._private.position.y,\n        nodeWidth + overlayPadding * 2,\n        nodeHeight + overlayPadding * 2\n      );\n\n      context.fill();\n    }\n  }\n\n};\n\n// does the node have at least one pie piece?\nCRp.hasPie = function(node){\n  node = node[0]; // ensure ele ref\n\n  return node._private.hasPie;\n};\n\nCRp.drawPie = function( context, node, nodeOpacity ){\n  node = node[0]; // ensure ele ref\n\n  var _p = node._private;\n  var cyStyle = node.cy().style();\n  var style = _p.style;\n  var pieSize = style['pie-size'];\n  var nodeW = node.width();\n  var nodeH = node.height();\n  var x = _p.position.x;\n  var y = _p.position.y;\n  var radius = Math.min( nodeW, nodeH ) / 2; // must fit in node\n  var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]\n  var usePaths = this.usePaths();\n\n  if( usePaths ){\n    x = 0;\n    y = 0;\n  }\n\n  if( pieSize.units === '%' ){\n    radius = radius * pieSize.value / 100;\n  } else if( pieSize.pfValue !== undefined ){\n    radius = pieSize.pfValue / 2;\n  }\n\n  for( var i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N\n    var size = style['pie-' + i + '-background-size'].value;\n    var color = style['pie-' + i + '-background-color'].value;\n    var opacity = style['pie-' + i + '-background-opacity'].value * nodeOpacity;\n    var percent = size / 100; // map integer range [0, 100] to [0, 1]\n\n    // percent can't push beyond 1\n    if( percent + lastPercent > 1 ){\n      percent = 1 - lastPercent;\n    }\n\n    var angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise\n    var angleDelta = 2 * Math.PI * percent;\n    var angleEnd = angleStart + angleDelta;\n\n    // ignore if\n    // - zero size\n    // - we're already beyond the full circle\n    // - adding the current slice would go beyond the full circle\n    if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){\n      continue;\n    }\n\n    context.beginPath();\n    context.moveTo(x, y);\n    context.arc( x, y, radius, angleStart, angleEnd );\n    context.closePath();\n\n    this.fillStyle(context, color[0], color[1], color[2], opacity);\n\n    context.fill();\n\n    lastPercent += percent;\n  }\n\n};\n\n\nmodule.exports = CRp;\n","'use strict';\n\nvar CRp = {};\n\nvar util = require('../../../util');\nvar math = require('../../../math');\n\nvar motionBlurDelay = 100;\n\n// var isFirefox = typeof InstallTrigger !== 'undefined';\n\nCRp.getPixelRatio = function(){\n  var context = this.data.contexts[0];\n\n  if( this.forcedPixelRatio != null ){\n    return this.forcedPixelRatio;\n  }\n\n  var backingStore = context.backingStorePixelRatio ||\n    context.webkitBackingStorePixelRatio ||\n    context.mozBackingStorePixelRatio ||\n    context.msBackingStorePixelRatio ||\n    context.oBackingStorePixelRatio ||\n    context.backingStorePixelRatio || 1;\n\n  return (window.devicePixelRatio || 1) / backingStore;\n};\n\nCRp.paintCache = function(context){\n  var caches = this.paintCaches = this.paintCaches || [];\n  var needToCreateCache = true;\n  var cache;\n\n  for(var i = 0; i < caches.length; i++ ){\n    cache = caches[i];\n\n    if( cache.context === context ){\n      needToCreateCache = false;\n      break;\n    }\n  }\n\n  if( needToCreateCache ){\n    cache = {\n      context: context\n    };\n    caches.push( cache );\n  }\n\n  return cache;\n};\n\nCRp.fillStyle = function(context, r, g, b, a){\n  context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // turn off for now, seems context does its own caching\n\n  // var cache = this.paintCache(context);\n\n  // var fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // if( cache.fillStyle !== fillStyle ){\n  //   context.fillStyle = cache.fillStyle = fillStyle;\n  // }\n};\n\nCRp.strokeStyle = function(context, r, g, b, a){\n  context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // turn off for now, seems context does its own caching\n\n  // var cache = this.paintCache(context);\n\n  // var strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n  // if( cache.strokeStyle !== strokeStyle ){\n  //   context.strokeStyle = cache.strokeStyle = strokeStyle;\n  // }\n};\n\nCRp.shadowStyle = function(context, color, opacity, blur, offsetX, offsetY){\n  var zoom = this.cy.zoom();\n\n  var cache = this.paintCache(context);\n\n  // don't make expensive changes to the shadow style if it's not used\n  if( cache.shadowOpacity === 0 && opacity === 0 ){\n    return;\n  }\n\n  cache.shadowOpacity = opacity;\n\n  if (opacity > 0) {\n    context.shadowBlur = blur * zoom;\n    context.shadowColor = \"rgba(\" + color[0] + \",\" + color[1] + \",\" + color[2] + \",\" + opacity + \")\";\n    context.shadowOffsetX = offsetX * zoom;\n    context.shadowOffsetY = offsetY * zoom;\n  } else {\n    context.shadowBlur = 0;\n    context.shadowColor = \"transparent\";\n  }\n};\n\n// Resize canvas\nCRp.matchCanvasSize = function(container) {\n  var r = this;\n  var data = r.data;\n  var width = container.clientWidth;\n  var height = container.clientHeight;\n  var pixelRatio = r.getPixelRatio();\n  var mbPxRatio = r.motionBlurPxRatio;\n\n  if(\n    container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE] ||\n    container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]\n  ){\n    pixelRatio = mbPxRatio;\n  }\n\n  var canvasWidth = width * pixelRatio;\n  var canvasHeight = height * pixelRatio;\n  var canvas;\n\n  if( canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight ){\n    return; // save cycles if same\n  }\n\n  r.fontCaches = null; // resizing resets the style\n\n  var canvasContainer = data.canvasContainer;\n  canvasContainer.style.width = width + 'px';\n  canvasContainer.style.height = height + 'px';\n\n  for (var i = 0; i < r.CANVAS_LAYERS; i++) {\n\n    canvas = data.canvases[i];\n\n    if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\n      canvas.width = canvasWidth;\n      canvas.height = canvasHeight;\n\n      canvas.style.width = width + 'px';\n      canvas.style.height = height + 'px';\n    }\n  }\n\n  for (var i = 0; i < r.BUFFER_COUNT; i++) {\n\n    canvas = data.bufferCanvases[i];\n\n    if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\n      canvas.width = canvasWidth;\n      canvas.height = canvasHeight;\n\n      canvas.style.width = width + 'px';\n      canvas.style.height = height + 'px';\n    }\n  }\n\n  r.textureMult = 1;\n  if( pixelRatio <= 1 ){\n    canvas = data.bufferCanvases[ r.TEXTURE_BUFFER ];\n\n    r.textureMult = 2;\n    canvas.width = canvasWidth * r.textureMult;\n    canvas.height = canvasHeight * r.textureMult;\n  }\n\n  r.canvasWidth = canvasWidth;\n  r.canvasHeight = canvasHeight;\n\n};\n\nCRp.renderTo = function( cxt, zoom, pan, pxRatio ){\n  this.render({\n    forcedContext: cxt,\n    forcedZoom: zoom,\n    forcedPan: pan,\n    drawAllLayers: true,\n    forcedPxRatio: pxRatio\n  });\n};\n\nCRp.render = function( options ) {\n  options = options || util.staticEmptyObject();\n\n  var forcedContext = options.forcedContext;\n  var drawAllLayers = options.drawAllLayers;\n  var drawOnlyNodeLayer = options.drawOnlyNodeLayer;\n  var forcedZoom = options.forcedZoom;\n  var forcedPan = options.forcedPan;\n  var r = this;\n  var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio;\n  var cy = r.cy; var data = r.data;\n  var needDraw = data.canvasNeedsRedraw;\n  var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming);\n  var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur;\n  var mbPxRatio = r.motionBlurPxRatio;\n  var hasCompoundNodes = cy.hasCompoundNodes();\n  var inNodeDragGesture = r.hoverData.draggingEles;\n  var inBoxSelection = r.hoverData.selecting || r.touchData.selecting ? true : false;\n  motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection;\n  var motionBlurFadeEffect = motionBlur;\n\n  if( !forcedContext && r.motionBlurTimeout ){\n    clearTimeout( r.motionBlurTimeout );\n  }\n\n  if( motionBlur ){\n    if( r.mbFrames == null ){\n      r.mbFrames = 0;\n    }\n\n    if( !r.drawingImage ){ // image loading frames don't count towards motion blur blurry frames\n      r.mbFrames++;\n    }\n\n    if( r.mbFrames < 3 ){ // need several frames before even high quality motionblur\n      motionBlurFadeEffect = false;\n    }\n\n    // go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing)\n    if( r.mbFrames > r.minMbLowQualFrames ){\n      //r.fullQualityMb = false;\n      r.motionBlurPxRatio = r.mbPxRBlurry;\n    }\n  }\n\n  if( r.clearingMotionBlur ){\n    r.motionBlurPxRatio = 1;\n  }\n\n  // b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame\n  // because a rogue async texture frame would clear needDraw\n  if( r.textureDrawLastFrame && !textureDraw ){\n    needDraw[r.NODE] = true;\n    needDraw[r.SELECT_BOX] = true;\n  }\n\n  var edges = r.getCachedEdges();\n  var coreStyle = cy.style()._private.coreStyle;\n\n  var zoom = cy.zoom();\n  var effectiveZoom = forcedZoom !== undefined ? forcedZoom : zoom;\n  var pan = cy.pan();\n  var effectivePan = {\n    x: pan.x,\n    y: pan.y\n  };\n\n  var vp = {\n    zoom: zoom,\n    pan: {\n      x: pan.x,\n      y: pan.y\n    }\n  };\n  var prevVp = r.prevViewport;\n  var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y;\n\n  // we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed)\n  if( !viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes) ){\n    r.motionBlurPxRatio = 1;\n  }\n\n  if( forcedPan ){\n    effectivePan = forcedPan;\n  }\n\n  // apply pixel ratio\n\n  effectiveZoom *= pixelRatio;\n  effectivePan.x *= pixelRatio;\n  effectivePan.y *= pixelRatio;\n\n  var eles = {\n    drag: {\n      nodes: [],\n      edges: [],\n      eles: []\n    },\n    nondrag: {\n      nodes: [],\n      edges: [],\n      eles: []\n    }\n  };\n\n  function mbclear( context, x, y, w, h ){\n    var gco = context.globalCompositeOperation;\n\n    context.globalCompositeOperation = 'destination-out';\n    r.fillStyle( context, 255, 255, 255, r.motionBlurTransparency );\n    context.fillRect(x, y, w, h);\n\n    context.globalCompositeOperation = gco;\n  }\n\n  function setContextTransform(context, clear){\n    var ePan, eZoom, w, h;\n\n    if( !r.clearingMotionBlur && (context === data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] || context === data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG]) ){\n      ePan = {\n        x: pan.x * mbPxRatio,\n        y: pan.y * mbPxRatio\n      };\n\n      eZoom = zoom * mbPxRatio;\n\n      w = r.canvasWidth * mbPxRatio;\n      h = r.canvasHeight * mbPxRatio;\n    } else {\n      ePan = effectivePan;\n      eZoom = effectiveZoom;\n\n      w = r.canvasWidth;\n      h = r.canvasHeight;\n    }\n\n    context.setTransform(1, 0, 0, 1, 0, 0);\n\n    if( clear === 'motionBlur' ){\n      mbclear(context, 0, 0, w, h);\n    } else if( !forcedContext && (clear === undefined || clear) ){\n      context.clearRect(0, 0, w, h);\n    }\n\n    if( !drawAllLayers ){\n      context.translate( ePan.x, ePan.y );\n      context.scale( eZoom, eZoom );\n    }\n    if( forcedPan ){\n      context.translate( forcedPan.x, forcedPan.y );\n    }\n    if( forcedZoom ){\n      context.scale( forcedZoom, forcedZoom );\n    }\n  }\n\n  if( !textureDraw ){\n    r.textureDrawLastFrame = false;\n  }\n\n  if( textureDraw ){\n    r.textureDrawLastFrame = true;\n\n    var bb;\n\n    if( !r.textureCache ){\n      r.textureCache = {};\n\n      bb = r.textureCache.bb = cy.elements().boundingBox();\n\n      r.textureCache.texture = r.data.bufferCanvases[ r.TEXTURE_BUFFER ];\n\n      var cxt = r.data.bufferContexts[ r.TEXTURE_BUFFER ];\n\n      cxt.setTransform(1, 0, 0, 1, 0, 0);\n      cxt.clearRect(0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult);\n\n      r.render({\n        forcedContext: cxt,\n        drawOnlyNodeLayer: true,\n        forcedPxRatio: pixelRatio * r.textureMult\n      });\n\n      var vp = r.textureCache.viewport = {\n        zoom: cy.zoom(),\n        pan: cy.pan(),\n        width: r.canvasWidth,\n        height: r.canvasHeight\n      };\n\n      vp.mpan = {\n        x: (0 - vp.pan.x)/vp.zoom,\n        y: (0 - vp.pan.y)/vp.zoom\n      };\n    }\n\n    needDraw[r.DRAG] = false;\n    needDraw[r.NODE] = false;\n\n    var context = data.contexts[r.NODE];\n\n    var texture = r.textureCache.texture;\n    var vp = r.textureCache.viewport;\n    bb = r.textureCache.bb;\n\n    context.setTransform(1, 0, 0, 1, 0, 0);\n\n    if( motionBlur ){\n      mbclear(context, 0, 0, vp.width, vp.height);\n    } else {\n      context.clearRect(0, 0, vp.width, vp.height);\n    }\n\n    var outsideBgColor = coreStyle['outside-texture-bg-color'].value;\n    var outsideBgOpacity = coreStyle['outside-texture-bg-opacity'].value;\n    r.fillStyle( context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity );\n    context.fillRect( 0, 0, vp.width, vp.height );\n\n    var zoom = cy.zoom();\n\n    setContextTransform( context, false );\n\n    context.clearRect( vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );\n    context.drawImage( texture, vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );\n\n  } else if( r.textureOnViewport && !forcedContext ){ // clear the cache since we don't need it\n    r.textureCache = null;\n  }\n\n  var vpManip = (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles);\n  var hideEdges = r.hideEdgesOnViewport && vpManip;\n  var hideLabels = r.hideLabelsOnViewport && vpManip;\n\n  if (needDraw[r.DRAG] || needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer) {\n    if( hideEdges ){\n    } else {\n      r.findEdgeControlPoints(edges);\n    }\n\n    var zEles = r.getCachedZSortedEles();\n    var extent = cy.extent();\n\n    for (var i = 0; i < zEles.length; i++) {\n      var ele = zEles[i];\n      var list;\n      var bb = forcedContext ? null : ele.boundingBox();\n      var insideExtent = forcedContext ? true : math.boundingBoxesIntersect( extent, bb );\n\n      if( !insideExtent ){ continue; } // no need to render\n\n      if ( ele._private.rscratch.inDragLayer ) {\n        list = eles.drag;\n      } else {\n        list = eles.nondrag;\n      }\n\n      list.eles.push( ele );\n    }\n\n  }\n\n\n  function drawElements( list, context ){\n    var eles = list.eles;\n\n    for( var i = 0; i < eles.length; i++ ){\n      var ele = eles[i];\n\n      if( ele.isNode() ){\n        r.drawNode(context, ele);\n\n        if( !hideLabels ){\n          r.drawNodeText(context, ele);\n        }\n\n        r.drawNode(context, ele, true);\n      } else if( !hideEdges ) {\n        r.drawEdge(context, ele);\n\n        if( !hideLabels ){\n          r.drawEdgeText(context, ele);\n        }\n\n        r.drawEdge(context, ele, true);\n      }\n\n\n    }\n\n  }\n\n  var needMbClear = [];\n\n  needMbClear[r.NODE] = !needDraw[r.NODE] && motionBlur && !r.clearedForMotionBlur[r.NODE] || r.clearingMotionBlur;\n  if( needMbClear[r.NODE] ){ r.clearedForMotionBlur[r.NODE] = true; }\n\n  needMbClear[r.DRAG] = !needDraw[r.DRAG] && motionBlur && !r.clearedForMotionBlur[r.DRAG] || r.clearingMotionBlur;\n  if( needMbClear[r.DRAG] ){ r.clearedForMotionBlur[r.DRAG] = true; }\n\n  if( needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer || needMbClear[r.NODE] ){\n    var useBuffer = motionBlur && !needMbClear[r.NODE] && mbPxRatio !== 1;\n    var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] : data.contexts[r.NODE] );\n    var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined;\n\n    setContextTransform( context, clear );\n    drawElements(eles.nondrag, context);\n\n    if( !drawAllLayers && !motionBlur ){\n      needDraw[r.NODE] = false;\n    }\n  }\n\n  if ( !drawOnlyNodeLayer && (needDraw[r.DRAG] || drawAllLayers || needMbClear[r.DRAG]) ) {\n    var useBuffer = motionBlur && !needMbClear[r.DRAG] && mbPxRatio !== 1;\n    var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ] : data.contexts[r.DRAG] );\n\n    setContextTransform( context, motionBlur && !useBuffer ? 'motionBlur' : undefined );\n    drawElements(eles.drag, context);\n\n    if( !drawAllLayers && !motionBlur ){\n      needDraw[r.DRAG] = false;\n    }\n  }\n\n  if( r.showFps || (!drawOnlyNodeLayer && (needDraw[r.SELECT_BOX] && !drawAllLayers)) ) {\n    var context = forcedContext || data.contexts[r.SELECT_BOX];\n\n    setContextTransform( context );\n\n    if( r.selection[4] == 1 && ( r.hoverData.selecting || r.touchData.selecting ) ){\n      var zoom = r.cy.zoom();\n      var borderWidth = coreStyle['selection-box-border-width'].value / zoom;\n\n      context.lineWidth = borderWidth;\n      context.fillStyle = \"rgba(\"\n        + coreStyle['selection-box-color'].value[0] + \",\"\n        + coreStyle['selection-box-color'].value[1] + \",\"\n        + coreStyle['selection-box-color'].value[2] + \",\"\n        + coreStyle['selection-box-opacity'].value + \")\";\n\n      context.fillRect(\n        r.selection[0],\n        r.selection[1],\n        r.selection[2] - r.selection[0],\n        r.selection[3] - r.selection[1]);\n\n      if (borderWidth > 0) {\n        context.strokeStyle = \"rgba(\"\n          + coreStyle['selection-box-border-color'].value[0] + \",\"\n          + coreStyle['selection-box-border-color'].value[1] + \",\"\n          + coreStyle['selection-box-border-color'].value[2] + \",\"\n          + coreStyle['selection-box-opacity'].value + \")\";\n\n        context.strokeRect(\n          r.selection[0],\n          r.selection[1],\n          r.selection[2] - r.selection[0],\n          r.selection[3] - r.selection[1]);\n      }\n    }\n\n    if( data.bgActivePosistion && !r.hoverData.selecting ){\n      var zoom = r.cy.zoom();\n      var pos = data.bgActivePosistion;\n\n      context.fillStyle = \"rgba(\"\n        + coreStyle['active-bg-color'].value[0] + \",\"\n        + coreStyle['active-bg-color'].value[1] + \",\"\n        + coreStyle['active-bg-color'].value[2] + \",\"\n        + coreStyle['active-bg-opacity'].value + \")\";\n\n      context.beginPath();\n      context.arc(pos.x, pos.y, coreStyle['active-bg-size'].pfValue / zoom, 0, 2 * Math.PI);\n      context.fill();\n    }\n\n    var timeToRender = r.lastRedrawTime;\n    if( r.showFps && timeToRender ){\n      timeToRender = Math.round( timeToRender );\n      var fps = Math.round(1000/timeToRender);\n\n      context.setTransform(1, 0, 0, 1, 0, 0);\n\n      context.fillStyle = 'rgba(255, 0, 0, 0.75)';\n      context.strokeStyle = 'rgba(255, 0, 0, 0.75)';\n      context.lineWidth = 1;\n      context.fillText( '1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20);\n\n      var maxFps = 60;\n      context.strokeRect(0, 30, 250, 20);\n      context.fillRect(0, 30, 250 * Math.min(fps/maxFps, 1), 20);\n    }\n\n    if( !drawAllLayers ){\n      needDraw[r.SELECT_BOX] = false;\n    }\n  }\n\n  // motionblur: blit rendered blurry frames\n  if( motionBlur && mbPxRatio !== 1 ){\n    var cxtNode = data.contexts[r.NODE];\n    var txtNode = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ];\n\n    var cxtDrag = data.contexts[r.DRAG];\n    var txtDrag = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ];\n\n    var drawMotionBlur = function( cxt, txt, needClear ){\n      cxt.setTransform(1, 0, 0, 1, 0, 0);\n\n      if( needClear || !motionBlurFadeEffect ){\n        cxt.clearRect( 0, 0, r.canvasWidth, r.canvasHeight );\n      } else {\n        mbclear( cxt, 0, 0, r.canvasWidth, r.canvasHeight );\n      }\n\n      var pxr = mbPxRatio;\n\n      cxt.drawImage(\n        txt, // img\n        0, 0, // sx, sy\n        r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh\n        0, 0, // x, y\n        r.canvasWidth, r.canvasHeight // w, h\n      );\n    };\n\n    if( needDraw[r.NODE] || needMbClear[r.NODE] ){\n      drawMotionBlur( cxtNode, txtNode, needMbClear[r.NODE] );\n      needDraw[r.NODE] = false;\n    }\n\n    if( needDraw[r.DRAG] || needMbClear[r.DRAG] ){\n      drawMotionBlur( cxtDrag, txtDrag, needMbClear[r.DRAG] );\n      needDraw[r.DRAG] = false;\n    }\n  }\n\n  r.currentlyDrawing = false;\n\n  r.prevViewport = vp;\n\n  if( r.clearingMotionBlur ){\n    r.clearingMotionBlur = false;\n    r.motionBlurCleared = true;\n    r.motionBlur = true;\n  }\n\n  if( motionBlur ){\n    r.motionBlurTimeout = setTimeout(function(){\n      r.motionBlurTimeout = null;\n\n      r.clearedForMotionBlur[r.NODE] = false;\n      r.clearedForMotionBlur[r.DRAG] = false;\n      r.motionBlur = false;\n      r.clearingMotionBlur = !textureDraw;\n      r.mbFrames = 0;\n\n      needDraw[r.NODE] = true;\n      needDraw[r.DRAG] = true;\n\n      r.redraw();\n    }, motionBlurDelay);\n  }\n\n  r.drawingImage = false;\n\n\n  if( !forcedContext && !r.initrender ){\n    r.initrender = true;\n    cy.trigger('initrender');\n  }\n\n  if( !forcedContext ){\n    cy.triggerOnRender();\n  }\n\n};\n\nmodule.exports = CRp;\n","'use strict';\n\n  var math = require('../../../math');\n\n  var CRp = {};\n\n  // @O Polygon drawing\n  CRp.drawPolygonPath = function(\n    context, x, y, width, height, points) {\n\n    var halfW = width / 2;\n    var halfH = height / 2;\n\n    if( context.beginPath ){ context.beginPath(); }\n\n    context.moveTo( x + halfW * points[0], y + halfH * points[1] );\n\n    for (var i = 1; i < points.length / 2; i++) {\n      context.lineTo( x + halfW * points[i * 2], y + halfH * points[i * 2 + 1] );\n    }\n\n    context.closePath();\n  };\n\n  // Round rectangle drawing\n  CRp.drawRoundRectanglePath = function(\n    context, x, y, width, height, radius) {\n\n    var halfWidth = width / 2;\n    var halfHeight = height / 2;\n    var cornerRadius = math.getRoundRectangleRadius(width, height);\n\n    if( context.beginPath ){ context.beginPath(); }\n\n    // Start at top middle\n    context.moveTo(x, y - halfHeight);\n    // Arc from middle top to right side\n    context.arcTo(x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius);\n    // Arc from right side to bottom\n    context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius);\n    // Arc from bottom to left side\n    context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius);\n    // Arc from left side to topBorder\n    context.arcTo(x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius);\n    // Join line\n    context.lineTo(x, y - halfHeight);\n\n\n    context.closePath();\n  };\n\n  var sin0 = Math.sin(0);\n  var cos0 = Math.cos(0);\n\n  var sin = {};\n  var cos = {};\n\n  var ellipseStepSize = Math.PI / 40;\n\n  for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {\n    sin[i] = Math.sin(i);\n    cos[i] = Math.cos(i);\n  }\n\n  CRp.drawEllipsePath = function(context, centerX, centerY, width, height){\n    if( context.beginPath ){ context.beginPath(); }\n\n    if( context.ellipse ){\n      context.ellipse( centerX, centerY, width/2, height/2, 0, 0, 2*Math.PI );\n    } else {\n      var xPos, yPos;\n      var rw = width/2;\n      var rh = height/2;\n      for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {\n        xPos = centerX - (rw * sin[i]) * sin0 + (rw * cos[i]) * cos0;\n        yPos = centerY + (rh * cos[i]) * sin0 + (rh * sin[i]) * cos0;\n\n        if (i === 0) {\n          context.moveTo(xPos, yPos);\n        } else {\n          context.lineTo(xPos, yPos);\n        }\n      }\n    }\n\n    context.closePath();\n  };\n\nmodule.exports = CRp;\n","'use strict';\n\nvar is = require('../../../is');\n\nvar CRp = {};\n\nCRp.createBuffer = function(w, h) {\n  var buffer = document.createElement('canvas');\n  buffer.width = w;\n  buffer.height = h;\n\n  return [buffer, buffer.getContext('2d')];\n};\n\nCRp.bufferCanvasImage = function( options ){\n  var cy = this.cy;\n  var bb = cy.elements().boundingBox();\n  var width = options.full ? Math.ceil(bb.w) : this.container.clientWidth;\n  var height = options.full ? Math.ceil(bb.h) : this.container.clientHeight;\n  var scale = 1;\n\n  if( options.scale !== undefined ){\n    width *= options.scale;\n    height *= options.scale;\n\n    scale = options.scale;\n  } else if( is.number(options.maxWidth) || is.number(options.maxHeight) ){\n    var maxScaleW = Infinity;\n    var maxScaleH = Infinity;\n\n    if( is.number(options.maxWidth) ){\n      maxScaleW = scale * options.maxWidth / width;\n    }\n\n    if( is.number(options.maxHeight) ){\n      maxScaleH = scale * options.maxHeight / height;\n    }\n\n    scale = Math.min( maxScaleW, maxScaleH );\n\n    width *= scale;\n    height *= scale;\n  }\n\n  var buffCanvas = document.createElement('canvas');\n\n  buffCanvas.width = width;\n  buffCanvas.height = height;\n\n  buffCanvas.style.width = width + 'px';\n  buffCanvas.style.height = height + 'px';\n\n  var buffCxt = buffCanvas.getContext('2d');\n\n  // Rasterize the layers, but only if container has nonzero size\n  if (width > 0 && height > 0) {\n\n    buffCxt.clearRect( 0, 0, width, height );\n\n    if( options.bg ){\n      buffCxt.fillStyle = options.bg;\n      buffCxt.rect( 0, 0, width, height );\n      buffCxt.fill();\n    }\n\n    buffCxt.globalCompositeOperation = 'source-over';\n\n    if( options.full ){ // draw the full bounds of the graph\n      this.render({\n        forcedContext: buffCxt,\n        drawAllLayers: true,\n        forcedZoom: scale,\n        forcedPan: { x: -bb.x1*scale, y: -bb.y1*scale },\n        forcedPxRatio: 1\n      });\n    } else { // draw the current view\n      var cyPan = cy.pan();\n      var pan = {\n        x: cyPan.x * scale,\n        y: cyPan.y * scale\n      };\n      var zoom = cy.zoom() * scale;\n\n      this.render({\n        forcedContext: buffCxt,\n        drawAllLayers: true,\n        forcedZoom: zoom,\n        forcedPan: pan,\n        forcedPxRatio: 1\n      });\n    }\n  }\n\n  return buffCanvas;\n};\n\nCRp.png = function( options ){\n  return this.bufferCanvasImage( options ).toDataURL('image/png');\n};\n\nCRp.jpg = function( options ){\n  return this.bufferCanvasImage( options ).toDataURL('image/jpeg');\n};\n\nmodule.exports = CRp;\n","/*\nThe canvas renderer was written by Yue Dong.\n\nModifications tracked on Github.\n*/\n\n'use strict';\n\nvar util = require('../../../util');\nvar is = require('../../../is');\n\nvar CR = CanvasRenderer;\nvar CRp = CanvasRenderer.prototype;\n\nCRp.CANVAS_LAYERS = 3;\n//\nCRp.SELECT_BOX = 0;\nCRp.DRAG = 1;\nCRp.NODE = 2;\n\nCRp.BUFFER_COUNT = 3;\n//\nCRp.TEXTURE_BUFFER = 0;\nCRp.MOTIONBLUR_BUFFER_NODE = 1;\nCRp.MOTIONBLUR_BUFFER_DRAG = 2;\n\nfunction CanvasRenderer(options) {\n  var r = this;\n\n  r.data = {\n    canvases: new Array(CRp.CANVAS_LAYERS),\n    contexts: new Array(CRp.CANVAS_LAYERS),\n    canvasNeedsRedraw: new Array(CRp.CANVAS_LAYERS),\n\n    bufferCanvases: new Array(CRp.BUFFER_COUNT),\n    bufferContexts: new Array(CRp.CANVAS_LAYERS)\n  };\n\n  r.data.canvasContainer = document.createElement('div');\n  var containerStyle = r.data.canvasContainer.style;\n  r.data.canvasContainer.setAttribute('style', '-webkit-tap-highlight-color: rgba(0,0,0,0);');\n  containerStyle.position = 'relative';\n  containerStyle.zIndex = '0';\n  containerStyle.overflow = 'hidden';\n\n  var container = options.cy.container();\n  container.appendChild( r.data.canvasContainer );\n  container.setAttribute('style', ( container.getAttribute('style') || '' ) + '-webkit-tap-highlight-color: rgba(0,0,0,0);');\n\n  for (var i = 0; i < CRp.CANVAS_LAYERS; i++) {\n    var canvas = r.data.canvases[i] = document.createElement('canvas');\n    r.data.contexts[i] = canvas.getContext('2d');\n    canvas.setAttribute( 'style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + ( is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : '' ) );\n    canvas.style.position = 'absolute';\n    canvas.setAttribute('data-id', 'layer' + i);\n    canvas.style.zIndex = String(CRp.CANVAS_LAYERS - i);\n    r.data.canvasContainer.appendChild(canvas);\n\n    r.data.canvasNeedsRedraw[i] = false;\n  }\n  r.data.topCanvas = r.data.canvases[0];\n\n  r.data.canvases[CRp.NODE].setAttribute('data-id', 'layer' + CRp.NODE + '-node');\n  r.data.canvases[CRp.SELECT_BOX].setAttribute('data-id', 'layer' + CRp.SELECT_BOX + '-selectbox');\n  r.data.canvases[CRp.DRAG].setAttribute('data-id', 'layer' + CRp.DRAG + '-drag');\n\n  for (var i = 0; i < CRp.BUFFER_COUNT; i++) {\n    r.data.bufferCanvases[i] = document.createElement('canvas');\n    r.data.bufferContexts[i] = r.data.bufferCanvases[i].getContext('2d');\n    r.data.bufferCanvases[i].style.position = 'absolute';\n    r.data.bufferCanvases[i].setAttribute('data-id', 'buffer' + i);\n    r.data.bufferCanvases[i].style.zIndex = String(-i - 1);\n    r.data.bufferCanvases[i].style.visibility = 'hidden';\n    //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]);\n  }\n\n  r.pathsEnabled = true;\n}\n\nCRp.redrawHint = function( group, bool ){\n  var r = this;\n\n  switch( group ){\n    case 'eles':\n      r.data.canvasNeedsRedraw[ CRp.NODE ] = bool;\n      break;\n    case 'drag':\n      r.data.canvasNeedsRedraw[ CRp.DRAG ] = bool;\n      break;\n    case 'select':\n      r.data.canvasNeedsRedraw[ CRp.SELECT_BOX ] = bool;\n      break;\n  }\n};\n\n// whether to use Path2D caching for drawing\nvar pathsImpld = typeof Path2D !== 'undefined';\n\nCRp.path2dEnabled = function( on ){\n  if( on === undefined ){\n    return this.pathsEnabled;\n  }\n\n  this.pathsEnabled = on ? true : false;\n};\n\nCRp.usePaths = function(){\n  return pathsImpld && this.pathsEnabled;\n};\n\n[\n  require('./arrow-shapes'),\n  require('./drawing-edges'),\n  require('./drawing-images'),\n  require('./drawing-label-text'),\n  require('./drawing-nodes'),\n  require('./drawing-redraw'),\n  require('./drawing-shapes'),\n  require('./export-image'),\n  require('./node-shapes')\n].forEach(function( props ){\n  util.extend( CRp, props );\n});\n\nmodule.exports = CR;\n","'use strict';\n\nvar CRp = {};\n\nvar impl;\n\nCRp.nodeShapeImpl = function( name ){\n  var self = this;\n\n  return ( impl || (impl = {\n    'ellipse': function( context, centerX, centerY, width, height ){\n      self.drawEllipsePath( context, centerX, centerY, width, height );\n    },\n\n    'polygon': function( context, centerX, centerY, width, height, points ){\n      self.drawPolygonPath( context, centerX, centerY, width, height, points );\n    },\n\n    'roundrectangle': function( context, centerX, centerY, width, height ){\n      self.drawRoundRectanglePath( context, centerX, centerY, width, height, 10 );\n    }\n  }) )[ name ];\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nmodule.exports = [\n  { name: 'null', impl: require('./null') },\n  { name: 'base', impl: require('./base') },\n  { name: 'canvas', impl: require('./canvas') }\n];\n","'use strict';\n\nfunction NullRenderer(options){\n  this.options = options;\n  this.notifications = 0; // for testing\n}\n\nvar noop = function(){};\n\nNullRenderer.prototype = {\n  recalculateRenderedStyle: noop,\n  notify: function(){ this.notifications++; },\n  init: noop\n};\n\nmodule.exports = NullRenderer;\n","'use strict';\n\nvar is = require('./is');\nvar util = require('./util');\nvar Thread = require('./thread');\nvar Promise = require('./promise');\nvar define = require('./define');\n\nvar Fabric = function( N ){\n  if( !(this instanceof Fabric) ){\n    return new Fabric( N );\n  }\n\n  this._private = {\n    pass: []\n  };\n\n  var defN = 4;\n\n  if( is.number(N) ){\n    // then use the specified number of threads\n  } if( typeof navigator !== 'undefined' && navigator.hardwareConcurrency != null ){\n    N = navigator.hardwareConcurrency;\n  } else {\n    try{\n      N = require('os').cpus().length;\n    } catch( err ){\n      N = defN;\n    }\n  } // TODO could use an estimation here but would the additional expense be worth it?\n\n  for( var i = 0; i < N; i++ ){\n    this[i] = new Thread();\n  }\n\n  this.length = N;\n};\n\nvar fabfn = Fabric.prototype; // short alias\n\nutil.extend(fabfn, {\n\n  instanceString: function(){ return 'fabric'; },\n\n  // require fn in all threads\n  require: function( fn, as ){\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n\n      thread.require( fn, as );\n    }\n\n    return this;\n  },\n\n  // get a random thread\n  random: function(){\n    var i = Math.round( (this.length - 1) * Math.random() );\n    var thread = this[i];\n\n    return thread;\n  },\n\n  // run on random thread\n  run: function( fn ){\n    var pass = this._private.pass.shift();\n\n    return this.random().pass( pass ).run( fn );\n  },\n\n  // sends a random thread a message\n  message: function( m ){\n    return this.random().message( m );\n  },\n\n  // send all threads a message\n  broadcast: function( m ){\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n\n      thread.message( m );\n    }\n\n    return this; // chaining\n  },\n\n  // stop all threads\n  stop: function(){\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n\n      thread.stop();\n    }\n\n    return this; // chaining\n  },\n\n  // pass data to be used with .spread() etc.\n  pass: function( data ){\n    var pass = this._private.pass;\n\n    if( is.array(data) ){\n      pass.push( data );\n    } else {\n      throw 'Only arrays may be used with fabric.pass()';\n    }\n\n    return this; // chaining\n  },\n\n  spreadSize: function(){\n    var subsize =  Math.ceil( this._private.pass[0].length / this.length );\n\n    subsize = Math.max( 1, subsize ); // don't pass less than one ele to each thread\n\n    return subsize;\n  },\n\n  // split the data into slices to spread the data equally among threads\n  spread: function( fn ){\n    var self = this;\n    var _p = self._private;\n    var subsize = self.spreadSize(); // number of pass eles to handle in each thread\n    var pass = _p.pass.shift().concat([]); // keep a copy\n    var runPs = [];\n\n    for( var i = 0; i < this.length; i++ ){\n      var thread = this[i];\n      var slice = pass.splice( 0, subsize );\n\n      var runP = thread.pass( slice ).run( fn );\n\n      runPs.push( runP );\n\n      var doneEarly = pass.length === 0;\n      if( doneEarly ){ break; }\n    }\n\n    return Promise.all( runPs ).then(function( thens ){\n      var postpass = [];\n      var p = 0;\n\n      // fill postpass with the total result joined from all threads\n      for( var i = 0; i < thens.length; i++ ){\n        var then = thens[i]; // array result from thread i\n\n        for( var j = 0; j < then.length; j++ ){\n          var t = then[j]; // array element\n\n          postpass[ p++ ] = t;\n        }\n      }\n\n      return postpass;\n    });\n  },\n\n  // parallel version of array.map()\n  map: function( fn ){\n    var self = this;\n\n    self.require( fn, '_$_$_fabmap' );\n\n    return self.spread(function( split ){\n      var mapped = [];\n      var origResolve = resolve; // jshint ignore:line\n\n      resolve = function( val ){ // jshint ignore:line\n        mapped.push( val );\n      };\n\n      for( var i = 0; i < split.length; i++ ){\n        var oldLen = mapped.length;\n        var ret = _$_$_fabmap( split[i] ); // jshint ignore:line\n        var nothingInsdByResolve = oldLen === mapped.length;\n\n        if( nothingInsdByResolve ){\n          mapped.push( ret );\n        }\n      }\n\n      resolve = origResolve; // jshint ignore:line\n\n      return mapped;\n    });\n\n  },\n\n  // parallel version of array.filter()\n  filter: function( fn ){\n    var _p = this._private;\n    var pass = _p.pass[0];\n\n    return this.map( fn ).then(function( include ){\n      var ret = [];\n\n      for( var i = 0; i < pass.length; i++ ){\n        var datum = pass[i];\n        var incDatum = include[i];\n\n        if( incDatum ){\n          ret.push( datum );\n        }\n      }\n\n      return ret;\n    });\n  },\n\n  // sorts the passed array using a divide and conquer strategy\n  sort: function( cmp ){\n    var self = this;\n    var P = this._private.pass[0].length;\n    var subsize = this.spreadSize();\n\n    cmp = cmp || function( a, b ){ // default comparison function\n      if( a < b ){\n        return -1;\n      } else if( a > b ){\n        return 1;\n      }\n\n      return 0;\n    };\n\n    self.require( cmp, '_$_$_cmp' );\n\n    return self.spread(function( split ){ // sort each split normally\n      var sortedSplit = split.sort( _$_$_cmp ); // jshint ignore:line\n      resolve( sortedSplit ); // jshint ignore:line\n\n    }).then(function( joined ){\n      // do all the merging in the main thread to minimise data transfer\n\n      // TODO could do merging in separate threads but would incur add'l cost of data transfer\n      // for each level of the merge\n\n      var merge = function( i, j, max ){\n        // don't overflow array\n        j = Math.min( j, P );\n        max = Math.min( max, P );\n\n        // left and right sides of merge\n        var l = i;\n        var r = j;\n\n        var sorted = [];\n\n        for( var k = l; k < max; k++ ){\n\n          var eleI = joined[i];\n          var eleJ = joined[j];\n\n          if( i < r && ( j >= max || cmp(eleI, eleJ) <= 0 ) ){\n            sorted.push( eleI );\n            i++;\n          } else {\n            sorted.push( eleJ );\n            j++;\n          }\n\n        }\n\n        // in the array proper, put the sorted values\n        for( var k = 0; k < sorted.length; k++ ){ // kth sorted item\n          var index = l + k;\n\n          joined[ index ] = sorted[k];\n        }\n      };\n\n      for( var splitL = subsize; splitL < P; splitL *= 2 ){ // merge until array is \"split\" as 1\n\n        for( var i = 0; i < P; i += 2*splitL ){\n          merge( i, i + splitL, i + 2*splitL );\n        }\n\n      }\n\n      return joined;\n    });\n  }\n\n\n});\n\nvar defineRandomPasser = function( opts ){\n  opts = opts || {};\n\n  return function( fn, arg1 ){\n    var pass = this._private.pass.shift();\n\n    return this.random().pass( pass )[ opts.threadFn ]( fn, arg1 );\n  };\n};\n\nutil.extend(fabfn, {\n  randomMap: defineRandomPasser({ threadFn: 'map' }),\n\n  reduce: defineRandomPasser({ threadFn: 'reduce' }),\n\n  reduceRight: defineRandomPasser({ threadFn: 'reduceRight' })\n});\n\n// aliases\nvar fn = fabfn;\nfn.promise = fn.run;\nfn.terminate = fn.halt = fn.stop;\nfn.include = fn.require;\n\n// pull in event apis\nutil.extend(fabfn, {\n  on: define.on(),\n  one: define.on({ unbindSelfOnTrigger: true }),\n  off: define.off(),\n  trigger: define.trigger()\n});\n\ndefine.eventAliasesOn( fabfn );\n\nmodule.exports = Fabric;\n","'use strict';\n/* jshint ignore:start */\n\n// Generated by CoffeeScript 1.8.0\n(function() {\n  var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;\n\n  floor = Math.floor, min = Math.min;\n\n\n  /*\n  Default comparison function to be used\n   */\n\n  defaultCmp = function(x, y) {\n    if (x < y) {\n      return -1;\n    }\n    if (x > y) {\n      return 1;\n    }\n    return 0;\n  };\n\n\n  /*\n  Insert item x in list a, and keep it sorted assuming a is sorted.\n\n  If x is already in a, insert it to the right of the rightmost x.\n\n  Optional args lo (default 0) and hi (default a.length) bound the slice\n  of a to be searched.\n   */\n\n  insort = function(a, x, lo, hi, cmp) {\n    var mid;\n    if (lo == null) {\n      lo = 0;\n    }\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (lo < 0) {\n      throw new Error('lo must be non-negative');\n    }\n    if (hi == null) {\n      hi = a.length;\n    }\n    while (lo < hi) {\n      mid = floor((lo + hi) / 2);\n      if (cmp(x, a[mid]) < 0) {\n        hi = mid;\n      } else {\n        lo = mid + 1;\n      }\n    }\n    return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);\n  };\n\n\n  /*\n  Push item onto heap, maintaining the heap invariant.\n   */\n\n  heappush = function(array, item, cmp) {\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    array.push(item);\n    return _siftdown(array, 0, array.length - 1, cmp);\n  };\n\n\n  /*\n  Pop the smallest item off the heap, maintaining the heap invariant.\n   */\n\n  heappop = function(array, cmp) {\n    var lastelt, returnitem;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    lastelt = array.pop();\n    if (array.length) {\n      returnitem = array[0];\n      array[0] = lastelt;\n      _siftup(array, 0, cmp);\n    } else {\n      returnitem = lastelt;\n    }\n    return returnitem;\n  };\n\n\n  /*\n  Pop and return the current smallest value, and add the new item.\n\n  This is more efficient than heappop() followed by heappush(), and can be\n  more appropriate when using a fixed size heap. Note that the value\n  returned may be larger than item! That constrains reasonable use of\n  this routine unless written as part of a conditional replacement:\n      if item > array[0]\n        item = heapreplace(array, item)\n   */\n\n  heapreplace = function(array, item, cmp) {\n    var returnitem;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    returnitem = array[0];\n    array[0] = item;\n    _siftup(array, 0, cmp);\n    return returnitem;\n  };\n\n\n  /*\n  Fast version of a heappush followed by a heappop.\n   */\n\n  heappushpop = function(array, item, cmp) {\n    var _ref;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (array.length && cmp(array[0], item) < 0) {\n      _ref = [array[0], item], item = _ref[0], array[0] = _ref[1];\n      _siftup(array, 0, cmp);\n    }\n    return item;\n  };\n\n\n  /*\n  Transform list into a heap, in-place, in O(array.length) time.\n   */\n\n  heapify = function(array, cmp) {\n    var i, _i, _j, _len, _ref, _ref1, _results, _results1;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    _ref1 = (function() {\n      _results1 = [];\n      for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }\n      return _results1;\n    }).apply(this).reverse();\n    _results = [];\n    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n      i = _ref1[_i];\n      _results.push(_siftup(array, i, cmp));\n    }\n    return _results;\n  };\n\n\n  /*\n  Update the position of the given item in the heap.\n  This function should be called every time the item is being modified.\n   */\n\n  updateItem = function(array, item, cmp) {\n    var pos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    pos = array.indexOf(item);\n    if (pos === -1) {\n      return;\n    }\n    _siftdown(array, 0, pos, cmp);\n    return _siftup(array, pos, cmp);\n  };\n\n\n  /*\n  Find the n largest elements in a dataset.\n   */\n\n  nlargest = function(array, n, cmp) {\n    var elem, result, _i, _len, _ref;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    result = array.slice(0, n);\n    if (!result.length) {\n      return result;\n    }\n    heapify(result, cmp);\n    _ref = array.slice(n);\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      elem = _ref[_i];\n      heappushpop(result, elem, cmp);\n    }\n    return result.sort(cmp).reverse();\n  };\n\n\n  /*\n  Find the n smallest elements in a dataset.\n   */\n\n  nsmallest = function(array, n, cmp) {\n    var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (n * 10 <= array.length) {\n      result = array.slice(0, n).sort(cmp);\n      if (!result.length) {\n        return result;\n      }\n      los = result[result.length - 1];\n      _ref = array.slice(n);\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        elem = _ref[_i];\n        if (cmp(elem, los) < 0) {\n          insort(result, elem, 0, null, cmp);\n          result.pop();\n          los = result[result.length - 1];\n        }\n      }\n      return result;\n    }\n    heapify(array, cmp);\n    _results = [];\n    for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {\n      _results.push(heappop(array, cmp));\n    }\n    return _results;\n  };\n\n  _siftdown = function(array, startpos, pos, cmp) {\n    var newitem, parent, parentpos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    newitem = array[pos];\n    while (pos > startpos) {\n      parentpos = (pos - 1) >> 1;\n      parent = array[parentpos];\n      if (cmp(newitem, parent) < 0) {\n        array[pos] = parent;\n        pos = parentpos;\n        continue;\n      }\n      break;\n    }\n    return array[pos] = newitem;\n  };\n\n  _siftup = function(array, pos, cmp) {\n    var childpos, endpos, newitem, rightpos, startpos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    endpos = array.length;\n    startpos = pos;\n    newitem = array[pos];\n    childpos = 2 * pos + 1;\n    while (childpos < endpos) {\n      rightpos = childpos + 1;\n      if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {\n        childpos = rightpos;\n      }\n      array[pos] = array[childpos];\n      pos = childpos;\n      childpos = 2 * pos + 1;\n    }\n    array[pos] = newitem;\n    return _siftdown(array, startpos, pos, cmp);\n  };\n\n  Heap = (function() {\n    Heap.push = heappush;\n\n    Heap.pop = heappop;\n\n    Heap.replace = heapreplace;\n\n    Heap.pushpop = heappushpop;\n\n    Heap.heapify = heapify;\n\n    Heap.updateItem = updateItem;\n\n    Heap.nlargest = nlargest;\n\n    Heap.nsmallest = nsmallest;\n\n    function Heap(cmp) {\n      this.cmp = cmp != null ? cmp : defaultCmp;\n      this.nodes = [];\n    }\n\n    Heap.prototype.push = function(x) {\n      return heappush(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.pop = function() {\n      return heappop(this.nodes, this.cmp);\n    };\n\n    Heap.prototype.peek = function() {\n      return this.nodes[0];\n    };\n\n    Heap.prototype.contains = function(x) {\n      return this.nodes.indexOf(x) !== -1;\n    };\n\n    Heap.prototype.replace = function(x) {\n      return heapreplace(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.pushpop = function(x) {\n      return heappushpop(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.heapify = function() {\n      return heapify(this.nodes, this.cmp);\n    };\n\n    Heap.prototype.updateItem = function(x) {\n      return updateItem(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.clear = function() {\n      return this.nodes = [];\n    };\n\n    Heap.prototype.empty = function() {\n      return this.nodes.length === 0;\n    };\n\n    Heap.prototype.size = function() {\n      return this.nodes.length;\n    };\n\n    Heap.prototype.clone = function() {\n      var heap;\n      heap = new Heap();\n      heap.nodes = this.nodes.slice(0);\n      return heap;\n    };\n\n    Heap.prototype.toArray = function() {\n      return this.nodes.slice(0);\n    };\n\n    Heap.prototype.insert = Heap.prototype.push;\n\n    Heap.prototype.top = Heap.prototype.peek;\n\n    Heap.prototype.front = Heap.prototype.peek;\n\n    Heap.prototype.has = Heap.prototype.contains;\n\n    Heap.prototype.copy = Heap.prototype.clone;\n\n    return Heap;\n\n  })();\n\n  (function(root, factory) {\n    if (typeof define === 'function' && define.amd) {\n      return define([], factory);\n    } else if (typeof exports === 'object') {\n      return module.exports = factory();\n    } else {\n      return root.Heap = factory();\n    }\n  })(this, function() {\n    return Heap;\n  });\n\n}).call(this);\n\n/* jshint ignore:end */\n","'use strict';\n\nvar window = require('./window');\nvar is = require('./is');\nvar Core = require('./core');\nvar extension = require('./extension');\nvar registerJquery = require('./jquery-plugin');\nvar Stylesheet = require('./stylesheet');\nvar Thread = require('./thread');\nvar Fabric = require('./fabric');\n\nvar cytoscape = function( options ){ // jshint ignore:line\n  // if no options specified, use default\n  if( options === undefined ){\n    options = {};\n  }\n\n  // create instance\n  if( is.plainObject( options ) ){\n    return new Core( options );\n  }\n\n  // allow for registration of extensions\n  else if( is.string( options ) ) {\n    return extension.apply(extension, arguments);\n  }\n};\n\n// replaced by build system\ncytoscape.version = '{{VERSION}}';\n\n// try to register w/ jquery\nif( window && window.jQuery ){\n  registerJquery( window.jQuery, cytoscape );\n}\n\n// expose register api\ncytoscape.registerJquery = function( jQuery ){\n  registerJquery( jQuery, cytoscape );\n};\n\n// expose public apis (mostly for extensions)\ncytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet;\ncytoscape.thread = cytoscape.Thread = Thread;\ncytoscape.fabric = cytoscape.Fabric = Fabric;\n\nmodule.exports = cytoscape;\n","'use strict';\n\nvar window = require('./window');\nvar navigator = window ? window.navigator : null;\n\nvar typeofstr = typeof '';\nvar typeofobj = typeof {};\nvar typeoffn = typeof function(){};\nvar typeofhtmlele = typeof HTMLElement;\n\nvar instanceStr = function( obj ){\n  return obj && obj.instanceString && is.fn( obj.instanceString ) ? obj.instanceString() : null;\n};\n\nvar is = {\n  defined: function(obj){\n    return obj != null; // not undefined or null\n  },\n\n  string: function(obj){\n    return obj != null && typeof obj == typeofstr;\n  },\n\n  fn: function(obj){\n    return obj != null && typeof obj === typeoffn;\n  },\n\n  array: function(obj){\n    return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;\n  },\n\n  plainObject: function(obj){\n    return obj != null && typeof obj === typeofobj && !is.array(obj) && obj.constructor === Object;\n  },\n\n  object: function(obj){\n    return obj != null && typeof obj === typeofobj;\n  },\n\n  number: function(obj){\n    return obj != null && typeof obj === typeof 1 && !isNaN(obj);\n  },\n\n  integer: function( obj ){\n    return is.number(obj) && Math.floor(obj) === obj;\n  },\n\n  bool: function(obj){\n    return obj != null && typeof obj === typeof true;\n  },\n\n  htmlElement: function(obj){\n    if( 'undefined' === typeofhtmlele ){\n      return undefined;\n    } else {\n      return null != obj && obj instanceof HTMLElement;\n    }\n  },\n\n  elementOrCollection: function(obj){\n    return is.element(obj) || is.collection(obj);\n  },\n\n  element: function(obj){\n    return instanceStr(obj) === 'collection' && obj._private.single;\n  },\n\n  collection: function(obj){\n    return instanceStr(obj) === 'collection' && !obj._private.single;\n  },\n\n  core: function(obj){\n    return instanceStr(obj) === 'core';\n  },\n\n  style: function(obj){\n    return instanceStr(obj) === 'style';\n  },\n\n  stylesheet: function(obj){\n    return instanceStr(obj) === 'stylesheet';\n  },\n\n  event: function(obj){\n    return instanceStr(obj) === 'event';\n  },\n\n  thread: function(obj){\n    return instanceStr(obj) === 'thread';\n  },\n\n  fabric: function(obj){\n    return instanceStr(obj) === 'fabric';\n  },\n\n  emptyString: function(obj){\n    if( !obj ){ // null is empty\n      return true;\n    } else if( is.string(obj) ){\n      if( obj === '' || obj.match(/^\\s+$/) ){\n        return true; // empty string is empty\n      }\n    }\n\n    return false; // otherwise, we don't know what we've got\n  },\n\n  nonemptyString: function(obj){\n    if( obj && is.string(obj) && obj !== '' && !obj.match(/^\\s+$/) ){\n      return true;\n    }\n\n    return false;\n  },\n\n  domElement: function(obj){\n    if( typeof HTMLElement === 'undefined' ){\n      return false; // we're not in a browser so it doesn't matter\n    } else {\n      return obj instanceof HTMLElement;\n    }\n  },\n\n  boundingBox: function(obj){\n    return is.plainObject(obj) &&\n      is.number(obj.x1) && is.number(obj.x2) &&\n      is.number(obj.y1) && is.number(obj.y2)\n    ;\n  },\n\n  promise: function(obj){\n    return is.object(obj) && is.fn(obj.then);\n  },\n\n  touch: function(){\n    return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch );\n  },\n\n  gecko: function(){\n    return typeof InstallTrigger !== 'undefined' || ('MozAppearance' in document.documentElement.style);\n  },\n\n  webkit: function(){\n    return typeof webkitURL !== 'undefined' || ('WebkitAppearance' in document.documentElement.style);\n  },\n\n  chromium: function(){\n    return typeof chrome !== 'undefined';\n  },\n\n  khtml: function(){\n    return navigator && navigator.vendor.match(/kde/i); // probably a better way to detect this...\n  },\n\n  khtmlEtc: function(){\n    return is.khtml() || is.webkit() || is.chromium();\n  },\n\n  ms: function(){\n     return navigator && navigator.userAgent.match(/msie|trident|edge/i); // probably a better way to detect this...\n  },\n\n  windows: function(){\n    return navigator && navigator.appVersion.match(/Win/i);\n  },\n\n  mac: function(){\n    return navigator && navigator.appVersion.match(/Mac/i);\n  },\n\n  linux: function(){\n    return navigator && navigator.appVersion.match(/Linux/i);\n  },\n\n  unix: function(){\n    return navigator && navigator.appVersion.match(/X11/i);\n  }\n};\n\nmodule.exports = is;\n","'use strict';\n\nvar is = require('./is');\n\nvar cyReg = function( $ele ){\n  var d = $ele[0]._cyreg = $ele[0]._cyreg || {};\n\n  return d;\n};\n\nvar registerJquery = function( $, cytoscape ){\n  if( !$ ){ return; } // no jquery => don't need this\n\n  if( $.fn.cytoscape ){ return; } // already registered\n\n  // allow calls on a jQuery selector by proxying calls to $.cytoscape\n  // e.g. $(\"#foo\").cytoscape(options) => $.cytoscape(options) on #foo\n  $.fn.cytoscape = function(opts){\n    var $this = $(this);\n\n    // get object\n    if( opts === 'get' ){\n      return cyReg( $this ).cy;\n    }\n\n    // bind to ready\n    else if( is.fn(opts) ){\n\n      var ready = opts;\n      var cy = cyReg( $this ).cy;\n\n      if( cy && cy.isReady() ){ // already ready so just trigger now\n        cy.trigger('ready', [], ready);\n\n      } else { // not yet ready, so add to readies list\n        var data = cyReg( $this );\n        var readies = data.readies = data.readies || [];\n\n        readies.push( ready );\n      }\n\n    }\n\n    // proxy to create instance\n    else if( is.plainObject(opts) ){\n      return $this.each(function(){\n        var options = $.extend({}, opts, {\n          container: $(this)[0]\n        });\n\n        cytoscape(options);\n      });\n    }\n  };\n\n  // allow access to the global cytoscape object under jquery for legacy reasons\n  $.cytoscape = cytoscape;\n\n  // use short alias (cy) if not already defined\n  if( $.fn.cy == null && $.cy == null ){\n    $.fn.cy = $.fn.cytoscape;\n    $.cy = $.cytoscape;\n  }\n};\n\nmodule.exports = registerJquery;\n","'use strict';\n\nvar math = {};\n\nmath.signum = function(x){\n  if( x > 0 ){\n    return 1;\n  } else if( x < 0 ){\n    return -1;\n  } else {\n    return 0;\n  }\n};\n\nmath.distance = function( p1, p2 ){\n  return Math.sqrt( math.sqDistance(p1, p2) );\n};\n\nmath.sqDistance = function( p1, p2 ){\n  var dx = p2.x - p1.x;\n  var dy = p2.y - p1.y;\n\n  return dx*dx + dy*dy;\n};\n\n// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves\nmath.qbezierAt = function(p0, p1, p2, t){\n  return (1 - t)*(1 - t)*p0 + 2*(1 - t)*t*p1 + t*t*p2;\n};\n\nmath.qbezierPtAt = function(p0, p1, p2, t){\n  return {\n    x: math.qbezierAt( p0.x, p1.x, p2.x, t ),\n    y: math.qbezierAt( p0.y, p1.y, p2.y, t )\n  };\n};\n\n// makes a full bb (x1, y1, x2, y2, w, h) from implicit params\nmath.makeBoundingBox = function( bb ){\n  if( bb.x1 != null && bb.y1 != null ){\n    if( bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1 ){\n      return {\n        x1: bb.x1,\n        y1: bb.y1,\n        x2: bb.x2,\n        y2: bb.y2,\n        w: bb.x2 - bb.x1,\n        h: bb.y2 - bb.y1\n      };\n    } else if( bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0 ){\n      return {\n        x1: bb.x1,\n        y1: bb.y1,\n        x2: bb.x1 + bb.w,\n        y2: bb.y1 + bb.h,\n        w: bb.w,\n        h: bb.h\n      };\n    }\n  }\n};\n\nmath.boundingBoxesIntersect = function( bb1, bb2 ){\n  // case: one bb to right of other\n  if( bb1.x1 > bb2.x2 ){ return false; }\n  if( bb2.x1 > bb1.x2 ){ return false; }\n\n  // case: one bb to left of other\n  if( bb1.x2 < bb2.x1 ){ return false; }\n  if( bb2.x2 < bb1.x1 ){ return false; }\n\n  // case: one bb above other\n  if( bb1.y2 < bb2.y1 ){ return false; }\n  if( bb2.y2 < bb1.y1 ){ return false; }\n\n  // case: one bb below other\n  if( bb1.y1 > bb2.y2 ){ return false; }\n  if( bb2.y1 > bb1.y2 ){ return false; }\n\n  // otherwise, must have some overlap\n  return true;\n};\n\nmath.inBoundingBox = function( bb, x, y ){\n  return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2;\n};\n\nmath.pointInBoundingBox = function( bb, pt ){\n  return this.inBoundingBox( bb, pt.x, pt.y );\n};\n\nmath.roundRectangleIntersectLine = function(\n  x, y, nodeX, nodeY, width, height, padding) {\n\n  var cornerRadius = this.getRoundRectangleRadius(width, height);\n\n  var halfWidth = width / 2;\n  var halfHeight = height / 2;\n\n  // Check intersections with straight line segments\n  var straightLineIntersections;\n\n  // Top segment, left to right\n  {\n    var topStartX = nodeX - halfWidth + cornerRadius - padding;\n    var topStartY = nodeY - halfHeight - padding;\n    var topEndX = nodeX + halfWidth - cornerRadius + padding;\n    var topEndY = topStartY;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Right segment, top to bottom\n  {\n    var rightStartX = nodeX + halfWidth + padding;\n    var rightStartY = nodeY - halfHeight + cornerRadius - padding;\n    var rightEndX = rightStartX;\n    var rightEndY = nodeY + halfHeight - cornerRadius + padding;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Bottom segment, left to right\n  {\n    var bottomStartX = nodeX - halfWidth + cornerRadius - padding;\n    var bottomStartY = nodeY + halfHeight + padding;\n    var bottomEndX = nodeX + halfWidth - cornerRadius + padding;\n    var bottomEndY = bottomStartY;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Left segment, top to bottom\n  {\n    var leftStartX = nodeX - halfWidth - padding;\n    var leftStartY = nodeY - halfHeight + cornerRadius - padding;\n    var leftEndX = leftStartX;\n    var leftEndY = nodeY + halfHeight - cornerRadius + padding;\n\n    straightLineIntersections = this.finiteLinesIntersect(\n      x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false);\n\n    if (straightLineIntersections.length > 0) {\n      return straightLineIntersections;\n    }\n  }\n\n  // Check intersections with arc segments\n  var arcIntersections;\n\n  // Top Left\n  {\n    var topLeftCenterX = nodeX - halfWidth + cornerRadius;\n    var topLeftCenterY = nodeY - halfHeight + cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      topLeftCenterX, topLeftCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] <= topLeftCenterX\n      && arcIntersections[1] <= topLeftCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  // Top Right\n  {\n    var topRightCenterX = nodeX + halfWidth - cornerRadius;\n    var topRightCenterY = nodeY - halfHeight + cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      topRightCenterX, topRightCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] >= topRightCenterX\n      && arcIntersections[1] <= topRightCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  // Bottom Right\n  {\n    var bottomRightCenterX = nodeX + halfWidth - cornerRadius;\n    var bottomRightCenterY = nodeY + halfHeight - cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      bottomRightCenterX, bottomRightCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] >= bottomRightCenterX\n      && arcIntersections[1] >= bottomRightCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  // Bottom Left\n  {\n    var bottomLeftCenterX = nodeX - halfWidth + cornerRadius;\n    var bottomLeftCenterY = nodeY + halfHeight - cornerRadius;\n    arcIntersections = this.intersectLineCircle(\n      x, y, nodeX, nodeY,\n      bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding);\n\n    // Ensure the intersection is on the desired quarter of the circle\n    if (arcIntersections.length > 0\n      && arcIntersections[0] <= bottomLeftCenterX\n      && arcIntersections[1] >= bottomLeftCenterY) {\n      return [arcIntersections[0], arcIntersections[1]];\n    }\n  }\n\n  return []; // if nothing\n};\n\nmath.inLineVicinity = function(x, y, lx1, ly1, lx2, ly2, tolerance){\n  var t = tolerance;\n\n  var x1 = Math.min(lx1, lx2);\n  var x2 = Math.max(lx1, lx2);\n  var y1 = Math.min(ly1, ly2);\n  var y2 = Math.max(ly1, ly2);\n\n  return x1 - t <= x && x <= x2 + t\n    && y1 - t <= y && y <= y2 + t;\n};\n\nmath.inBezierVicinity = function(\n  x, y, x1, y1, x2, y2, x3, y3, tolerance) {\n\n  var bb = {\n    x1: Math.min( x1, x3, x2 ) - tolerance,\n    x2: Math.max( x1, x3, x2 ) + tolerance,\n    y1: Math.min( y1, y3, y2 ) - tolerance,\n    y2: Math.max( y1, y3, y2 ) + tolerance\n  };\n\n  // if outside the rough bounding box for the bezier, then it can't be a hit\n  if( x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2 ){\n    // console.log('bezier out of rough bb')\n    return false;\n  } else {\n    // console.log('do more expensive check');\n    return true;\n  }\n\n};\n\nmath.solveCubic = function(a, b, c, d, result) {\n\n  // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where\n  // r is the real component, i is the imaginary component\n\n  // An implementation of the Cardano method from the year 1545\n  // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots\n\n  b /= a;\n  c /= a;\n  d /= a;\n\n  var discriminant, q, r, dum1, s, t, term1, r13;\n\n  q = (3.0 * c - (b * b)) / 9.0;\n  r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b));\n  r /= 54.0;\n\n  discriminant = q * q * q + r * r;\n  result[1] = 0;\n  term1 = (b / 3.0);\n\n  if (discriminant > 0) {\n    s = r + Math.sqrt(discriminant);\n    s = ((s < 0) ? -Math.pow(-s, (1.0 / 3.0)) : Math.pow(s, (1.0 / 3.0)));\n    t = r - Math.sqrt(discriminant);\n    t = ((t < 0) ? -Math.pow(-t, (1.0 / 3.0)) : Math.pow(t, (1.0 / 3.0)));\n    result[0] = -term1 + s + t;\n    term1 += (s + t) / 2.0;\n    result[4] = result[2] = -term1;\n    term1 = Math.sqrt(3.0) * (-t + s) / 2;\n    result[3] = term1;\n    result[5] = -term1;\n    return;\n  }\n\n  result[5] = result[3] = 0;\n\n  if (discriminant === 0) {\n    r13 = ((r < 0) ? -Math.pow(-r, (1.0 / 3.0)) : Math.pow(r, (1.0 / 3.0)));\n    result[0] = -term1 + 2.0 * r13;\n    result[4] = result[2] = -(r13 + term1);\n    return;\n  }\n\n  q = -q;\n  dum1 = q * q * q;\n  dum1 = Math.acos(r / Math.sqrt(dum1));\n  r13 = 2.0 * Math.sqrt(q);\n  result[0] = -term1 + r13 * Math.cos(dum1 / 3.0);\n  result[2] = -term1 + r13 * Math.cos((dum1 + 2.0 * Math.PI) / 3.0);\n  result[4] = -term1 + r13 * Math.cos((dum1 + 4.0 * Math.PI) / 3.0);\n\n  return;\n};\n\nmath.sqDistanceToQuadraticBezier = function(\n  x, y, x1, y1, x2, y2, x3, y3) {\n\n  // Find minimum distance by using the minimum of the distance\n  // function between the given point and the curve\n\n  // This gives the coefficients of the resulting cubic equation\n  // whose roots tell us where a possible minimum is\n  // (Coefficients are divided by 4)\n\n  var a = 1.0 * x1*x1 - 4*x1*x2 + 2*x1*x3 + 4*x2*x2 - 4*x2*x3 + x3*x3\n    + y1*y1 - 4*y1*y2 + 2*y1*y3 + 4*y2*y2 - 4*y2*y3 + y3*y3;\n\n  var b = 1.0 * 9*x1*x2 - 3*x1*x1 - 3*x1*x3 - 6*x2*x2 + 3*x2*x3\n    + 9*y1*y2 - 3*y1*y1 - 3*y1*y3 - 6*y2*y2 + 3*y2*y3;\n\n  var c = 1.0 * 3*x1*x1 - 6*x1*x2 + x1*x3 - x1*x + 2*x2*x2 + 2*x2*x - x3*x\n    + 3*y1*y1 - 6*y1*y2 + y1*y3 - y1*y + 2*y2*y2 + 2*y2*y - y3*y;\n\n  var d = 1.0 * x1*x2 - x1*x1 + x1*x - x2*x\n    + y1*y2 - y1*y1 + y1*y - y2*y;\n\n  // debug(\"coefficients: \" + a / a + \", \" + b / a + \", \" + c / a + \", \" + d / a);\n\n  var roots = [];\n\n  // Use the cubic solving algorithm\n  this.solveCubic(a, b, c, d, roots);\n\n  var zeroThreshold = 0.0000001;\n\n  var params = [];\n\n  for (var index = 0; index < 6; index += 2) {\n    if (Math.abs(roots[index + 1]) < zeroThreshold\n        && roots[index] >= 0\n        && roots[index] <= 1.0) {\n      params.push(roots[index]);\n    }\n  }\n\n  params.push(1.0);\n  params.push(0.0);\n\n  var minDistanceSquared = -1;\n  var closestParam;\n\n  var curX, curY, distSquared;\n  for (var i = 0; i < params.length; i++) {\n    curX = Math.pow(1.0 - params[i], 2.0) * x1\n      + 2.0 * (1 - params[i]) * params[i] * x2\n      + params[i] * params[i] * x3;\n\n    curY = Math.pow(1 - params[i], 2.0) * y1\n      + 2 * (1.0 - params[i]) * params[i] * y2\n      + params[i] * params[i] * y3;\n\n    distSquared = Math.pow(curX - x, 2) + Math.pow(curY - y, 2);\n    // debug('distance for param ' + params[i] + \": \" + Math.sqrt(distSquared));\n    if (minDistanceSquared >= 0) {\n      if (distSquared < minDistanceSquared) {\n        minDistanceSquared = distSquared;\n        closestParam = params[i];\n      }\n    } else {\n      minDistanceSquared = distSquared;\n      closestParam = params[i];\n    }\n  }\n\n  return minDistanceSquared;\n};\n\nmath.sqDistanceToFiniteLine = function(x, y, x1, y1, x2, y2) {\n  var offset = [x - x1, y - y1];\n  var line = [x2 - x1, y2 - y1];\n\n  var lineSq = line[0] * line[0] + line[1] * line[1];\n  var hypSq = offset[0] * offset[0] + offset[1] * offset[1];\n\n  var dotProduct = offset[0] * line[0] + offset[1] * line[1];\n  var adjSq = dotProduct * dotProduct / lineSq;\n\n  if (dotProduct < 0) {\n    return hypSq;\n  }\n\n  if (adjSq > lineSq) {\n    return (x - x2) * (x - x2) + (y - y2) * (y - y2);\n  }\n\n  return hypSq - adjSq;\n};\n\nmath.pointInsidePolygonPoints = function(x, y, points){\n  var x1, y1, x2, y2;\n  var y3;\n\n  // Intersect with vertical line through (x, y)\n  var up = 0;\n  var down = 0;\n  for (var i = 0; i < points.length / 2; i++) {\n\n    x1 = points[i * 2];\n    y1 = points[i * 2 + 1];\n\n    if (i + 1 < points.length / 2) {\n      x2 = points[(i + 1) * 2];\n      y2 = points[(i + 1) * 2 + 1];\n    } else {\n      x2 = points[(i + 1 - points.length / 2) * 2];\n      y2 = points[(i + 1 - points.length / 2) * 2 + 1];\n    }\n\n    if (x1 == x && x2 == x) {\n\n    } else if ((x1 >= x && x >= x2)\n      || (x1 <= x && x <= x2)) {\n\n      y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1;\n\n      if (y3 > y) {\n        up++;\n      }\n\n      if (y3 < y) {\n        down++;\n      }\n\n    } else {\n      continue;\n    }\n\n  }\n\n  if (up % 2 === 0) {\n    return false;\n  } else {\n    return true;\n  }\n};\n\nmath.pointInsidePolygon = function(\n  x, y, basePoints, centerX, centerY, width, height, direction, padding) {\n\n  //var direction = arguments[6];\n  var transformedPoints = new Array(basePoints.length);\n\n  // Gives negative angle\n  var angle;\n\n  if( direction[0] != null ){\n    angle = Math.atan(direction[1] / direction[0]);\n\n    if (direction[0] < 0) {\n      angle = angle + Math.PI / 2;\n    } else {\n      angle = -angle - Math.PI / 2;\n    }\n  } else {\n    angle = direction;\n  }\n\n  var cos = Math.cos(-angle);\n  var sin = Math.sin(-angle);\n\n  //    console.log(\"base: \" + basePoints);\n  for (var i = 0; i < transformedPoints.length / 2; i++) {\n    transformedPoints[i * 2] =\n      width / 2 * (basePoints[i * 2] * cos\n        - basePoints[i * 2 + 1] * sin);\n\n    transformedPoints[i * 2 + 1] =\n      height / 2 * (basePoints[i * 2 + 1] * cos\n        + basePoints[i * 2] * sin);\n\n    transformedPoints[i * 2] += centerX;\n    transformedPoints[i * 2 + 1] += centerY;\n  }\n\n  var points;\n\n  if (padding > 0) {\n    var expandedLineSet = this.expandPolygon(\n      transformedPoints,\n      -padding);\n\n    points = this.joinLines(expandedLineSet);\n  } else {\n    points = transformedPoints;\n  }\n\n  return math.pointInsidePolygonPoints( x, y, points );\n};\n\nmath.joinLines = function(lineSet) {\n\n  var vertices = new Array(lineSet.length / 2);\n\n  var currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY;\n  var nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY;\n\n  for (var i = 0; i < lineSet.length / 4; i++) {\n    currentLineStartX = lineSet[i * 4];\n    currentLineStartY = lineSet[i * 4 + 1];\n    currentLineEndX = lineSet[i * 4 + 2];\n    currentLineEndY = lineSet[i * 4 + 3];\n\n    if (i < lineSet.length / 4 - 1) {\n      nextLineStartX = lineSet[(i + 1) * 4];\n      nextLineStartY = lineSet[(i + 1) * 4 + 1];\n      nextLineEndX = lineSet[(i + 1) * 4 + 2];\n      nextLineEndY = lineSet[(i + 1) * 4 + 3];\n    } else {\n      nextLineStartX = lineSet[0];\n      nextLineStartY = lineSet[1];\n      nextLineEndX = lineSet[2];\n      nextLineEndY = lineSet[3];\n    }\n\n    var intersection = this.finiteLinesIntersect(\n      currentLineStartX, currentLineStartY,\n      currentLineEndX, currentLineEndY,\n      nextLineStartX, nextLineStartY,\n      nextLineEndX, nextLineEndY,\n      true);\n\n    vertices[i * 2] = intersection[0];\n    vertices[i * 2 + 1] = intersection[1];\n  }\n\n  return vertices;\n};\n\nmath.expandPolygon = function(points, pad) {\n\n  var expandedLineSet = new Array(points.length * 2);\n\n  var currentPointX, currentPointY, nextPointX, nextPointY;\n\n  for (var i = 0; i < points.length / 2; i++) {\n    currentPointX = points[i * 2];\n    currentPointY = points[i * 2 + 1];\n\n    if (i < points.length / 2 - 1) {\n      nextPointX = points[(i + 1) * 2];\n      nextPointY = points[(i + 1) * 2 + 1];\n    } else {\n      nextPointX = points[0];\n      nextPointY = points[1];\n    }\n\n    // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY]\n\n    // Assume CCW polygon winding\n\n    var offsetX = (nextPointY - currentPointY);\n    var offsetY = -(nextPointX - currentPointX);\n\n    // Normalize\n    var offsetLength = Math.sqrt(offsetX * offsetX + offsetY * offsetY);\n    var normalizedOffsetX = offsetX / offsetLength;\n    var normalizedOffsetY = offsetY / offsetLength;\n\n    expandedLineSet[i * 4] = currentPointX + normalizedOffsetX * pad;\n    expandedLineSet[i * 4 + 1] = currentPointY + normalizedOffsetY * pad;\n    expandedLineSet[i * 4 + 2] = nextPointX + normalizedOffsetX * pad;\n    expandedLineSet[i * 4 + 3] = nextPointY + normalizedOffsetY * pad;\n  }\n\n  return expandedLineSet;\n};\n\nmath.intersectLineEllipse = function(\n  x, y, centerX, centerY, ellipseWradius, ellipseHradius) {\n\n  var dispX = centerX - x;\n  var dispY = centerY - y;\n\n  dispX /= ellipseWradius;\n  dispY /= ellipseHradius;\n\n  var len = Math.sqrt(dispX * dispX + dispY * dispY);\n\n  var newLength = len - 1;\n\n  if (newLength < 0) {\n    return [];\n  }\n\n  var lenProportion = newLength / len;\n\n  return [(centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y];\n};\n\n// Returns intersections of increasing distance from line's start point\nmath.intersectLineCircle = function(\n  x1, y1, x2, y2, centerX, centerY, radius) {\n\n  // Calculate d, direction vector of line\n  var d = [x2 - x1, y2 - y1]; // Direction vector of line\n  var c = [centerX, centerY]; // Center of circle\n  var f = [x1 - centerX, y1 - centerY];\n\n  var a = d[0] * d[0] + d[1] * d[1];\n  var b = 2 * (f[0] * d[0] + f[1] * d[1]);\n  var c = (f[0] * f[0] + f[1] * f[1]) - radius * radius ;\n\n  var discriminant = b*b-4*a*c;\n\n  if (discriminant < 0) {\n    return [];\n  }\n\n  var t1 = (-b + Math.sqrt(discriminant)) / (2 * a);\n  var t2 = (-b - Math.sqrt(discriminant)) / (2 * a);\n\n  var tMin = Math.min(t1, t2);\n  var tMax = Math.max(t1, t2);\n  var inRangeParams = [];\n\n  if (tMin >= 0 && tMin <= 1) {\n    inRangeParams.push(tMin);\n  }\n\n  if (tMax >= 0 && tMax <= 1) {\n    inRangeParams.push(tMax);\n  }\n\n  if (inRangeParams.length === 0) {\n    return [];\n  }\n\n  var nearIntersectionX = inRangeParams[0] * d[0] + x1;\n  var nearIntersectionY = inRangeParams[0] * d[1] + y1;\n\n  if (inRangeParams.length > 1) {\n\n    if (inRangeParams[0] == inRangeParams[1]) {\n      return [nearIntersectionX, nearIntersectionY];\n    } else {\n\n      var farIntersectionX = inRangeParams[1] * d[0] + x1;\n      var farIntersectionY = inRangeParams[1] * d[1] + y1;\n\n      return [nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY];\n    }\n\n  } else {\n    return [nearIntersectionX, nearIntersectionY];\n  }\n\n};\n\nmath.findCircleNearPoint = function(centerX, centerY,\n  radius, farX, farY) {\n\n  var displacementX = farX - centerX;\n  var displacementY = farY - centerY;\n  var distance = Math.sqrt(displacementX * displacementX\n    + displacementY * displacementY);\n\n  var unitDisplacementX = displacementX / distance;\n  var unitDisplacementY = displacementY / distance;\n\n  return [centerX + unitDisplacementX * radius,\n    centerY + unitDisplacementY * radius];\n};\n\nmath.findMaxSqDistanceToOrigin = function(points) {\n  var maxSqDistance = 0.000001;\n  var sqDistance;\n\n  for (var i = 0; i < points.length / 2; i++) {\n\n    sqDistance = points[i * 2] * points[i * 2]\n      + points[i * 2 + 1] * points[i * 2 + 1];\n\n    if (sqDistance > maxSqDistance) {\n      maxSqDistance = sqDistance;\n    }\n  }\n\n  return maxSqDistance;\n};\n\nmath.finiteLinesIntersect = function(\n  x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines) {\n\n  var ua_t = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);\n  var ub_t = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);\n  var u_b = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);\n\n  if (u_b !== 0) {\n    var ua = ua_t / u_b;\n    var ub = ub_t / u_b;\n\n    if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n      return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];\n\n    } else {\n      if (!infiniteLines) {\n        return [];\n      } else {\n        return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];\n      }\n    }\n  } else {\n    if (ua_t === 0 || ub_t === 0) {\n\n      // Parallel, coincident lines. Check if overlap\n\n      // Check endpoint of second line\n      if ([x1, x2, x4].sort()[1] === x4) {\n        return [x4, y4];\n      }\n\n      // Check start point of second line\n      if ([x1, x2, x3].sort()[1] === x3) {\n        return [x3, y3];\n      }\n\n      // Endpoint of first line\n      if ([x3, x4, x2].sort()[1] === x2) {\n        return [x2, y2];\n      }\n\n      return [];\n    } else {\n\n      // Parallel, non-coincident\n      return [];\n    }\n  }\n};\n\nmath.polygonIntersectLine = function(\n  x, y, basePoints, centerX, centerY, width, height, padding) {\n\n  var intersections = [];\n  var intersection;\n\n  var transformedPoints = new Array(basePoints.length);\n\n  for (var i = 0; i < transformedPoints.length / 2; i++) {\n    transformedPoints[i * 2] = basePoints[i * 2] * width + centerX;\n    transformedPoints[i * 2 + 1] = basePoints[i * 2 + 1] * height + centerY;\n  }\n\n  var points;\n\n  if (padding > 0) {\n    var expandedLineSet = math.expandPolygon(\n      transformedPoints,\n      -padding);\n\n    points = math.joinLines(expandedLineSet);\n  } else {\n    points = transformedPoints;\n  }\n  // var points = transformedPoints;\n\n  var currentX, currentY, nextX, nextY;\n\n  for (var i = 0; i < points.length / 2; i++) {\n\n    currentX = points[i * 2];\n    currentY = points[i * 2 + 1];\n\n    if (i < points.length / 2 - 1) {\n      nextX = points[(i + 1) * 2];\n      nextY = points[(i + 1) * 2 + 1];\n    } else {\n      nextX = points[0];\n      nextY = points[1];\n    }\n\n    intersection = this.finiteLinesIntersect(\n      x, y, centerX, centerY,\n      currentX, currentY,\n      nextX, nextY);\n\n    if (intersection.length !== 0) {\n      intersections.push(intersection[0], intersection[1]);\n    }\n  }\n\n  return intersections;\n};\n\nmath.shortenIntersection = function(\n  intersection, offset, amount) {\n\n  var disp = [intersection[0] - offset[0], intersection[1] - offset[1]];\n\n  var length = Math.sqrt(disp[0] * disp[0] + disp[1] * disp[1]);\n\n  var lenRatio = (length - amount) / length;\n\n  if (lenRatio < 0) {\n    lenRatio = 0.00001;\n  }\n\n  return [offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1]];\n};\n\nmath.generateUnitNgonPointsFitToSquare = function(sides, rotationRadians) {\n  var points = math.generateUnitNgonPoints(sides, rotationRadians);\n  points = math.fitPolygonToSquare(points);\n\n  return points;\n};\n\nmath.fitPolygonToSquare = function(points){\n  var x, y;\n  var sides = points.length/2;\n  var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n\n  for (var i = 0; i < sides; i++) {\n    x = points[2 * i];\n    y = points[2 * i + 1];\n\n    minX = Math.min( minX, x );\n    maxX = Math.max( maxX, x );\n    minY = Math.min( minY, y );\n    maxY = Math.max( maxY, y );\n  }\n\n  // stretch factors\n  var sx = 2 / (maxX - minX);\n  var sy = 2 / (maxY - minY);\n\n  for (var i = 0; i < sides; i++){\n    x = points[2 * i] = points[2 * i] * sx;\n    y = points[2 * i + 1] = points[2 * i + 1] * sy;\n\n    minX = Math.min( minX, x );\n    maxX = Math.max( maxX, x );\n    minY = Math.min( minY, y );\n    maxY = Math.max( maxY, y );\n  }\n\n  if( minY < -1 ){\n    for (var i = 0; i < sides; i++){\n      y = points[2 * i + 1] = points[2 * i + 1] + (-1 -minY);\n    }\n  }\n\n  return points;\n};\n\nmath.generateUnitNgonPoints = function(sides, rotationRadians) {\n\n  var increment = 1.0 / sides * 2 * Math.PI;\n  var startAngle = sides % 2 === 0 ?\n    Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0;\n    //    console.log(nodeShapes['square']);\n  startAngle += rotationRadians;\n\n  var points = new Array(sides * 2);\n\n  var currentAngle, x, y;\n  for (var i = 0; i < sides; i++) {\n    currentAngle = i * increment + startAngle;\n\n    x = points[2 * i] = Math.cos(currentAngle);// * (1 + i/2);\n    y = points[2 * i + 1] = Math.sin(-currentAngle);//  * (1 + i/2);\n  }\n\n  return points;\n};\n\nmath.getRoundRectangleRadius = function(width, height) {\n\n  // Set the default radius, unless half of width or height is smaller than default\n  return Math.min(width / 4, height / 4, 8);\n};\n\nmodule.exports = math;\n","// internal, minimal Promise impl s.t. apis can return promises in old envs\n// based on thenable (http://github.com/rse/thenable)\n\n'use strict';\n\n/*  promise states [Promises/A+ 2.1]  */\nvar STATE_PENDING   = 0;                                         /*  [Promises/A+ 2.1.1]  */\nvar STATE_FULFILLED = 1;                                         /*  [Promises/A+ 2.1.2]  */\nvar STATE_REJECTED  = 2;                                         /*  [Promises/A+ 2.1.3]  */\n\n/*  promise object constructor  */\nvar api = function (executor) {\n  /*  optionally support non-constructor/plain-function call  */\n  if (!(this instanceof api))\n    return new api(executor);\n\n  /*  initialize object  */\n  this.id           = \"Thenable/1.0.7\";\n  this.state        = STATE_PENDING; /*  initial state  */\n  this.fulfillValue = undefined;     /*  initial value  */     /*  [Promises/A+ 1.3, 2.1.2.2]  */\n  this.rejectReason = undefined;     /*  initial reason */     /*  [Promises/A+ 1.5, 2.1.3.2]  */\n  this.onFulfilled  = [];            /*  initial handlers  */\n  this.onRejected   = [];            /*  initial handlers  */\n\n  /*  provide optional information-hiding proxy  */\n  this.proxy = {\n    then: this.then.bind(this)\n  };\n\n  /*  support optional executor function  */\n  if (typeof executor === \"function\")\n    executor.call(this, this.fulfill.bind(this), this.reject.bind(this));\n};\n\n/*  promise API methods  */\napi.prototype = {\n  /*  promise resolving methods  */\n  fulfill: function (value) { return deliver(this, STATE_FULFILLED, \"fulfillValue\", value); },\n  reject:  function (value) { return deliver(this, STATE_REJECTED,  \"rejectReason\", value); },\n\n  /*  \"The then Method\" [Promises/A+ 1.1, 1.2, 2.2]  */\n  then: function (onFulfilled, onRejected) {\n    var curr = this;\n    var next = new api();                                    /*  [Promises/A+ 2.2.7]  */\n    curr.onFulfilled.push(\n      resolver(onFulfilled, next, \"fulfill\"));             /*  [Promises/A+ 2.2.2/2.2.6]  */\n    curr.onRejected.push(\n      resolver(onRejected,  next, \"reject\" ));             /*  [Promises/A+ 2.2.3/2.2.6]  */\n    execute(curr);\n    return next.proxy;                                       /*  [Promises/A+ 2.2.7, 3.3]  */\n  }\n};\n\n/*  deliver an action  */\nvar deliver = function (curr, state, name, value) {\n  if (curr.state === STATE_PENDING) {\n    curr.state = state;                                      /*  [Promises/A+ 2.1.2.1, 2.1.3.1]  */\n    curr[name] = value;                                      /*  [Promises/A+ 2.1.2.2, 2.1.3.2]  */\n    execute(curr);\n  }\n  return curr;\n};\n\n/*  execute all handlers  */\nvar execute = function (curr) {\n  if (curr.state === STATE_FULFILLED)\n    execute_handlers(curr, \"onFulfilled\", curr.fulfillValue);\n  else if (curr.state === STATE_REJECTED)\n    execute_handlers(curr, \"onRejected\",  curr.rejectReason);\n};\n\n/*  execute particular set of handlers  */\nvar execute_handlers = function (curr, name, value) {\n  /* global setImmediate: true */\n  /* global setTimeout: true */\n\n  /*  short-circuit processing  */\n  if (curr[name].length === 0)\n    return;\n\n  /*  iterate over all handlers, exactly once  */\n  var handlers = curr[name];\n  curr[name] = [];                                             /*  [Promises/A+ 2.2.2.3, 2.2.3.3]  */\n  var func = function () {\n    for (var i = 0; i < handlers.length; i++)\n      handlers[i](value);                                  /*  [Promises/A+ 2.2.5]  */\n  };\n\n  /*  execute procedure asynchronously  */                     /*  [Promises/A+ 2.2.4, 3.1]  */\n  if (typeof setImmediate === \"function\")\n    setImmediate(func);\n  else\n    setTimeout(func, 0);\n};\n\n/*  generate a resolver function  */\nvar resolver = function (cb, next, method) {\n  return function (value) {\n    if (typeof cb !== \"function\")                            /*  [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4]  */\n      next[method].call(next, value);                      /*  [Promises/A+ 2.2.7.3, 2.2.7.4]  */\n    else {\n      var result;\n      try { result = cb(value); }                          /*  [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2]  */\n      catch (e) {\n        next.reject(e);                                  /*  [Promises/A+ 2.2.7.2]  */\n        return;\n      }\n      resolve(next, result);                               /*  [Promises/A+ 2.2.7.1]  */\n    }\n  };\n};\n\n/*  \"Promise Resolution Procedure\"  */                           /*  [Promises/A+ 2.3]  */\nvar resolve = function (promise, x) {\n  /*  sanity check arguments  */                               /*  [Promises/A+ 2.3.1]  */\n  if (promise === x || promise.proxy === x) {\n    promise.reject(new TypeError(\"cannot resolve promise with itself\"));\n    return;\n  }\n\n  /*  surgically check for a \"then\" method\n    (mainly to just call the \"getter\" of \"then\" only once)  */\n  var then;\n  if ((typeof x === \"object\" && x !== null) || typeof x === \"function\") {\n    try { then = x.then; }                                   /*  [Promises/A+ 2.3.3.1, 3.5]  */\n    catch (e) {\n      promise.reject(e);                                   /*  [Promises/A+ 2.3.3.2]  */\n      return;\n    }\n  }\n\n  /*  handle own Thenables    [Promises/A+ 2.3.2]\n    and similar \"thenables\" [Promises/A+ 2.3.3]  */\n  if (typeof then === \"function\") {\n    var resolved = false;\n    try {\n      /*  call retrieved \"then\" method */                  /*  [Promises/A+ 2.3.3.3]  */\n      then.call(x,\n        /*  resolvePromise  */                           /*  [Promises/A+ 2.3.3.3.1]  */\n        function (y) {\n          if (resolved) return; resolved = true;       /*  [Promises/A+ 2.3.3.3.3]  */\n          if (y === x)                                 /*  [Promises/A+ 3.6]  */\n            promise.reject(new TypeError(\"circular thenable chain\"));\n          else\n            resolve(promise, y);\n        },\n\n        /*  rejectPromise  */                            /*  [Promises/A+ 2.3.3.3.2]  */\n        function (r) {\n          if (resolved) return; resolved = true;       /*  [Promises/A+ 2.3.3.3.3]  */\n          promise.reject(r);\n        }\n      );\n    }\n    catch (e) {\n      if (!resolved)                                       /*  [Promises/A+ 2.3.3.3.3]  */\n        promise.reject(e);                               /*  [Promises/A+ 2.3.3.3.4]  */\n    }\n    return;\n  }\n\n  /*  handle other values  */\n  promise.fulfill(x);                                          /*  [Promises/A+ 2.3.4, 2.3.3.4]  */\n};\n\n// use native promises where possible\nvar Promise = typeof Promise === 'undefined' ? api : Promise;\n\n// so we always have Promise.all()\nPromise.all = Promise.all || function( ps ){\n  return new Promise(function( resolveAll, rejectAll ){\n    var vals = new Array( ps.length );\n    var doneCount = 0;\n\n    var fulfill = function( i, val ){\n      vals[i] = val;\n      doneCount++;\n\n      if( doneCount === ps.length ){\n        resolveAll( vals );\n      }\n    };\n\n    for( var i = 0; i < ps.length; i++ ){\n      (function( i ){\n        var p = ps[i];\n        var isPromise = p.then != null;\n\n        if( isPromise ){\n          p.then(function( val ){\n            fulfill( i, val );\n          }, function( err ){\n            rejectAll( err );\n          });\n        } else {\n          var val = p;\n          fulfill( i, val );\n        }\n      })( i );\n    }\n\n  });\n};\n\nmodule.exports = Promise;\n","'use strict';\n\nvar is = require('./is');\nvar util = require('./util');\n\nvar Selector = function( onlyThisGroup, selector ){\n\n  if( !(this instanceof Selector) ){\n    return new Selector(onlyThisGroup, selector);\n  }\n\n  if( selector === undefined && onlyThisGroup !== undefined ){\n    selector = onlyThisGroup;\n    onlyThisGroup = undefined;\n  }\n\n  var self = this;\n\n  self._private = {\n    selectorText: null,\n    invalid: true\n  };\n\n  if( !selector || ( is.string(selector) && selector.match(/^\\s*$/) ) ){\n\n    if( onlyThisGroup == null ){\n      // ignore\n      self.length = 0;\n    } else {\n      self[0] = newQuery();\n      self[0].group = onlyThisGroup;\n      self.length = 1;\n    }\n\n  } else if( is.elementOrCollection( selector ) ){\n    var collection = selector.collection();\n\n    self[0] = newQuery();\n    self[0].collection = collection;\n    self.length = 1;\n\n  } else if( is.fn( selector ) ) {\n    self[0] = newQuery();\n    self[0].filter = selector;\n    self.length = 1;\n\n  } else if( is.string( selector ) ){\n\n    // the current subject in the query\n    var currentSubject = null;\n\n    // storage for parsed queries\n    var newQuery = function(){\n      return {\n        classes: [],\n        colonSelectors: [],\n        data: [],\n        group: null,\n        ids: [],\n        meta: [],\n\n        // fake selectors\n        collection: null, // a collection to match against\n        filter: null, // filter function\n\n        // these are defined in the upward direction rather than down (e.g. child)\n        // because we need to go up in Selector.filter()\n        parent: null, // parent query obj\n        ancestor: null, // ancestor query obj\n        subject: null, // defines subject in compound query (subject query obj; points to self if subject)\n\n        // use these only when subject has been defined\n        child: null,\n        descendant: null\n      };\n    };\n\n    // tokens in the query language\n    var tokens = {\n      metaChar: '[\\\\!\\\\\"\\\\#\\\\$\\\\%\\\\&\\\\\\'\\\\(\\\\)\\\\*\\\\+\\\\,\\\\.\\\\/\\\\:\\\\;\\\\<\\\\=\\\\>\\\\?\\\\@\\\\[\\\\]\\\\^\\\\`\\\\{\\\\|\\\\}\\\\~]', // chars we need to escape in var names, etc\n      comparatorOp: '=|\\\\!=|>|>=|<|<=|\\\\$=|\\\\^=|\\\\*=', // binary comparison op (used in data selectors)\n      boolOp: '\\\\?|\\\\!|\\\\^', // boolean (unary) operators (used in data selectors)\n      string: '\"(?:\\\\\\\\\"|[^\"])+\"' + '|' + \"'(?:\\\\\\\\'|[^'])+'\", // string literals (used in data selectors) -- doublequotes | singlequotes\n      number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123\n      meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection)\n      separator: '\\\\s*,\\\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass\n      descendant: '\\\\s+',\n      child: '\\\\s+>\\\\s+',\n      subject: '\\\\$'\n    };\n    tokens.variable = '(?:[\\\\w-]|(?:\\\\\\\\'+ tokens.metaChar +'))+'; // a variable name\n    tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number\n    tokens.className = tokens.variable; // a class name (follows variable conventions)\n    tokens.id = tokens.variable; // an element id (follows variable conventions)\n\n    // when a token like a variable has escaped meta characters, we need to clean the backslashes out\n    // so that values get compared properly in Selector.filter()\n    var cleanMetaChars = function(str){\n      return str.replace(new RegExp('\\\\\\\\(' + tokens.metaChar + ')', 'g'), function(match, $1, offset, original){\n        return $1;\n      });\n    };\n\n    // add @ variants to comparatorOp\n    var ops = tokens.comparatorOp.split('|');\n    for( var i = 0; i < ops.length; i++ ){\n      var op = ops[i];\n      tokens.comparatorOp += '|@' + op;\n    }\n\n    // add ! variants to comparatorOp\n    var ops = tokens.comparatorOp.split('|');\n    for( var i = 0; i < ops.length; i++ ){\n      var op = ops[i];\n\n      if( op.indexOf('!') >= 0 ){ continue; } // skip ops that explicitly contain !\n      if( op === '=' ){ continue; } // skip = b/c != is explicitly defined\n\n      tokens.comparatorOp += '|\\\\!' + op;\n    }\n\n    // NOTE: add new expression syntax here to have it recognised by the parser;\n    // - a query contains all adjacent (i.e. no separator in between) expressions;\n    // - the current query is stored in self[i] --- you can use the reference to `this` in the populate function;\n    // - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward\n    // - when you add something here, also add to Selector.toString()\n    var exprs = [\n      {\n        name: 'group',\n        query: true,\n        regex: '(node|edge|\\\\*)',\n        populate: function( group ){\n          this.group = group == \"*\" ? group : group + 's';\n        }\n      },\n\n      {\n        name: 'state',\n        query: true,\n        // NB: if one colon selector is a substring of another from its start, place the longer one first\n        // e.g. :foobar|:foo\n        regex: '(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)',\n        populate: function( state ){\n          this.colonSelectors.push( state );\n        }\n      },\n\n      {\n        name: 'id',\n        query: true,\n        regex: '\\\\#('+ tokens.id +')',\n        populate: function( id ){\n          this.ids.push( cleanMetaChars(id) );\n        }\n      },\n\n      {\n        name: 'className',\n        query: true,\n        regex: '\\\\.('+ tokens.className +')',\n        populate: function( className ){\n          this.classes.push( cleanMetaChars(className) );\n        }\n      },\n\n      {\n        name: 'dataExists',\n        query: true,\n        regex: '\\\\[\\\\s*('+ tokens.variable +')\\\\s*\\\\]',\n        populate: function( variable ){\n          this.data.push({\n            field: cleanMetaChars(variable)\n          });\n        }\n      },\n\n      {\n        name: 'dataCompare',\n        query: true,\n        regex: '\\\\[\\\\s*('+ tokens.variable +')\\\\s*('+ tokens.comparatorOp +')\\\\s*('+ tokens.value +')\\\\s*\\\\]',\n        populate: function( variable, comparatorOp, value ){\n          var valueIsString = new RegExp('^' + tokens.string + '$').exec(value) != null;\n\n          if( valueIsString ){\n            value = value.substring(1, value.length - 1);\n          } else {\n            value = parseFloat(value);\n          }\n\n          this.data.push({\n            field: cleanMetaChars(variable),\n            operator: comparatorOp,\n            value: value\n          });\n        }\n      },\n\n      {\n        name: 'dataBool',\n        query: true,\n        regex: '\\\\[\\\\s*('+ tokens.boolOp +')\\\\s*('+ tokens.variable +')\\\\s*\\\\]',\n        populate: function( boolOp, variable ){\n          this.data.push({\n            field: cleanMetaChars(variable),\n            operator: boolOp\n          });\n        }\n      },\n\n      {\n        name: 'metaCompare',\n        query: true,\n        regex: '\\\\[\\\\[\\\\s*('+ tokens.meta +')\\\\s*('+ tokens.comparatorOp +')\\\\s*('+ tokens.number +')\\\\s*\\\\]\\\\]',\n        populate: function( meta, comparatorOp, number ){\n          this.meta.push({\n            field: cleanMetaChars(meta),\n            operator: comparatorOp,\n            value: parseFloat(number)\n          });\n        }\n      },\n\n      {\n        name: 'nextQuery',\n        separator: true,\n        regex: tokens.separator,\n        populate: function(){\n          // go on to next query\n          self[++i] = newQuery();\n          currentSubject = null;\n        }\n      },\n\n      {\n        name: 'child',\n        separator: true,\n        regex: tokens.child,\n        populate: function(){\n          // this query is the parent of the following query\n          var childQuery = newQuery();\n          childQuery.parent = this;\n          childQuery.subject = currentSubject;\n\n          // we're now populating the child query with expressions that follow\n          self[i] = childQuery;\n        }\n      },\n\n      {\n        name: 'descendant',\n        separator: true,\n        regex: tokens.descendant,\n        populate: function(){\n          // this query is the ancestor of the following query\n          var descendantQuery = newQuery();\n          descendantQuery.ancestor = this;\n          descendantQuery.subject = currentSubject;\n\n          // we're now populating the descendant query with expressions that follow\n          self[i] = descendantQuery;\n        }\n      },\n\n      {\n        name: 'subject',\n        modifier: true,\n        regex: tokens.subject,\n        populate: function(){\n          if( currentSubject != null && this.subject != this ){\n            util.error('Redefinition of subject in selector `' + selector + '`');\n            return false;\n          }\n\n          currentSubject = this;\n          this.subject = this;\n        }\n\n      }\n    ];\n\n    self._private.selectorText = selector;\n    var remaining = selector;\n    var i = 0;\n\n    // of all the expressions, find the first match in the remaining text\n    var consumeExpr = function( expectation ){\n      var expr;\n      var match;\n      var name;\n\n      for( var j = 0; j < exprs.length; j++ ){\n        var e = exprs[j];\n        var n = e.name;\n\n        // ignore this expression if it doesn't meet the expectation function\n        if( is.fn( expectation ) && !expectation(n, e) ){ continue; }\n\n        var m = remaining.match(new RegExp( '^' + e.regex ));\n\n        if( m != null ){\n          match = m;\n          expr = e;\n          name = n;\n\n          var consumed = m[0];\n          remaining = remaining.substring( consumed.length );\n\n          break; // we've consumed one expr, so we can return now\n        }\n      }\n\n      return {\n        expr: expr,\n        match: match,\n        name: name\n      };\n    };\n\n    // consume all leading whitespace\n    var consumeWhitespace = function(){\n      var match = remaining.match(/^\\s+/);\n\n      if( match ){\n        var consumed = match[0];\n        remaining = remaining.substring( consumed.length );\n      }\n    };\n\n    self[0] = newQuery(); // get started\n\n    consumeWhitespace(); // get rid of leading whitespace\n    for(;;){\n      var check = consumeExpr();\n\n      if( check.expr == null ){\n        util.error('The selector `'+ selector +'`is invalid');\n        return;\n      } else {\n        var args = [];\n        for(var j = 1; j < check.match.length; j++){\n          args.push( check.match[j] );\n        }\n\n        // let the token populate the selector object (i.e. in self[i])\n        var ret = check.expr.populate.apply( self[i], args );\n\n        if( ret === false ){ return; } // exit if population failed\n      }\n\n      // we're done when there's nothing left to parse\n      if( remaining.match(/^\\s*$/) ){\n        break;\n      }\n    }\n\n    self.length = i + 1;\n\n    // adjust references for subject\n    for(var j = 0; j < self.length; j++){\n      var query = self[j];\n\n      if( query.subject != null ){\n        // go up the tree until we reach the subject\n        for(;;){\n          if( query.subject == query ){ break; } // done if subject is self\n\n          if( query.parent != null ){ // swap parent/child reference\n            var parent = query.parent;\n            var child = query;\n\n            child.parent = null;\n            parent.child = child;\n\n            query = parent; // go up the tree\n          } else if( query.ancestor != null ){ // swap ancestor/descendant\n            var ancestor = query.ancestor;\n            var descendant = query;\n\n            descendant.ancestor = null;\n            ancestor.descendant = descendant;\n\n            query = ancestor; // go up the tree\n          } else {\n            util.error('When adjusting references for the selector `'+ query +'`, neither parent nor ancestor was found');\n            break;\n          }\n        } // for\n\n        self[j] = query.subject; // subject should be the root query\n      } // if\n    } // for\n\n    // make sure for each query that the subject group matches the implicit group if any\n    if( onlyThisGroup != null ){\n      for(var j = 0; j < self.length; j++){\n        if( self[j].group != null && self[j].group != onlyThisGroup ){\n          util.error('Group `'+ self[j].group +'` conflicts with implicit group `'+ onlyThisGroup +'` in selector `'+ selector +'`');\n          return;\n        }\n\n        self[j].group = onlyThisGroup; // set to implicit group\n      }\n    }\n\n  } else {\n    util.error('A selector must be created from a string; found ' + selector);\n    return;\n  }\n\n  self._private.invalid = false;\n\n};\n\nvar selfn = Selector.prototype;\n\nselfn.size = function(){\n  return this.length;\n};\n\nselfn.eq = function(i){\n  return this[i];\n};\n\nvar queryMatches = function(query, element){\n  // check group\n  if( query.group != null && query.group != '*' && query.group != element._private.group ){\n    return false;\n  }\n\n  var cy = element.cy();\n\n  // check colon selectors\n  var allColonSelectorsMatch = true;\n  for(var k = 0; k < query.colonSelectors.length; k++){\n    var sel = query.colonSelectors[k];\n\n    switch(sel){\n    case ':selected':\n      allColonSelectorsMatch = element.selected();\n      break;\n    case ':unselected':\n      allColonSelectorsMatch = !element.selected();\n      break;\n    case ':selectable':\n      allColonSelectorsMatch = element.selectable();\n      break;\n    case ':unselectable':\n      allColonSelectorsMatch = !element.selectable();\n      break;\n    case ':locked':\n      allColonSelectorsMatch = element.locked();\n      break;\n    case ':unlocked':\n      allColonSelectorsMatch = !element.locked();\n      break;\n    case ':visible':\n      allColonSelectorsMatch = element.visible();\n      break;\n    case ':hidden':\n      allColonSelectorsMatch = !element.visible();\n      break;\n    case ':transparent':\n      allColonSelectorsMatch = element.transparent();\n      break;\n    case ':grabbed':\n      allColonSelectorsMatch = element.grabbed();\n      break;\n    case ':free':\n      allColonSelectorsMatch = !element.grabbed();\n      break;\n    case ':removed':\n      allColonSelectorsMatch = element.removed();\n      break;\n    case ':inside':\n      allColonSelectorsMatch = !element.removed();\n      break;\n    case ':grabbable':\n      allColonSelectorsMatch = element.grabbable();\n      break;\n    case ':ungrabbable':\n      allColonSelectorsMatch = !element.grabbable();\n      break;\n    case ':animated':\n      allColonSelectorsMatch = element.animated();\n      break;\n    case ':unanimated':\n      allColonSelectorsMatch = !element.animated();\n      break;\n    case ':parent':\n      allColonSelectorsMatch = element.isNode() && element.children().nonempty();\n      break;\n    case ':child':\n    case ':nonorphan':\n      allColonSelectorsMatch = element.isNode() && element.parent().nonempty();\n      break;\n    case ':orphan':\n      allColonSelectorsMatch = element.isNode() && element.parent().empty();\n      break;\n    case ':loop':\n      allColonSelectorsMatch = element.isEdge() && element.data('source') === element.data('target');\n      break;\n    case ':simple':\n      allColonSelectorsMatch = element.isEdge() && element.data('source') !== element.data('target');\n      break;\n    case ':active':\n      allColonSelectorsMatch = element.active();\n      break;\n    case ':inactive':\n      allColonSelectorsMatch = !element.active();\n      break;\n    case ':touch':\n      allColonSelectorsMatch = is.touch();\n      break;\n    case ':backgrounding':\n      allColonSelectorsMatch = element.backgrounding();\n      break;\n    case ':nonbackgrounding':\n      allColonSelectorsMatch = !element.backgrounding();\n      break;\n    }\n\n    if( !allColonSelectorsMatch ) break;\n  }\n  if( !allColonSelectorsMatch ) return false;\n\n  // check id\n  var allIdsMatch = true;\n  for(var k = 0; k < query.ids.length; k++){\n    var id = query.ids[k];\n    var actualId = element._private.data.id;\n\n    allIdsMatch = allIdsMatch && (id == actualId);\n\n    if( !allIdsMatch ) break;\n  }\n  if( !allIdsMatch ) return false;\n\n  // check classes\n  var allClassesMatch = true;\n  for(var k = 0; k < query.classes.length; k++){\n    var cls = query.classes[k];\n\n    allClassesMatch = allClassesMatch && element.hasClass(cls);\n\n    if( !allClassesMatch ) break;\n  }\n  if( !allClassesMatch ) return false;\n\n  // generic checking for data/metadata\n  var operandsMatch = function(params){\n    var allDataMatches = true;\n    for(var k = 0; k < query[params.name].length; k++){\n      var data = query[params.name][k];\n      var operator = data.operator;\n      var value = data.value;\n      var field = data.field;\n      var matches;\n\n      if( operator != null && value != null ){\n\n        var fieldVal = params.fieldValue(field);\n        var fieldStr = !is.string(fieldVal) && !is.number(fieldVal) ? '' : '' + fieldVal;\n        var valStr = '' + value;\n\n        var caseInsensitive = false;\n        if( operator.indexOf('@') >= 0 ){\n          fieldStr = fieldStr.toLowerCase();\n          valStr = valStr.toLowerCase();\n\n          operator = operator.replace('@', '');\n          caseInsensitive = true;\n        }\n\n        var notExpr = false;\n        var handledNotExpr = false;\n        if( operator.indexOf('!') >= 0 ){\n          operator = operator.replace('!', '');\n          notExpr = true;\n        }\n\n        // if we're doing a case insensitive comparison, then we're using a STRING comparison\n        // even if we're comparing numbers\n        if( caseInsensitive ){\n          value = valStr.toLowerCase();\n          fieldVal = fieldStr.toLowerCase();\n        }\n\n        switch(operator){\n        case '*=':\n          matches = fieldStr.search(valStr) >= 0;\n          break;\n        case '$=':\n          matches = new RegExp(valStr + '$').exec(fieldStr) != null;\n          break;\n        case '^=':\n          matches = new RegExp('^' + valStr).exec(fieldStr) != null;\n          break;\n        case '=':\n          matches = fieldVal === value;\n          break;\n        case '!=':\n          matches = fieldVal !== value;\n          break;\n        case '>':\n          matches = !notExpr ? fieldVal > value : fieldVal <= value;\n          handledNotExpr = true;\n          break;\n        case '>=':\n          matches = !notExpr ? fieldVal >= value : fieldVal < value;\n          handledNotExpr = true;\n          break;\n        case '<':\n          matches = !notExpr ? fieldVal < value : fieldVal >= value;\n          handledNotExpr = true;\n          break;\n        case '<=':\n          matches = !notExpr ? fieldVal <= value : fieldVal > value;\n          handledNotExpr = true;\n          break;\n        default:\n          matches = false;\n          break;\n\n        }\n      } else if( operator != null ){\n        switch(operator){\n        case '?':\n          matches = params.fieldTruthy(field);\n          break;\n        case '!':\n          matches = !params.fieldTruthy(field);\n          break;\n        case '^':\n          matches = params.fieldUndefined(field);\n          break;\n        }\n      } else {\n        matches = !params.fieldUndefined(field);\n      }\n\n      if( notExpr && !handledNotExpr ){\n        matches = !matches;\n        handledNotExpr = true;\n      }\n\n      if( !matches ){\n        allDataMatches = false;\n        break;\n      }\n    } // for\n\n    return allDataMatches;\n  }; // operandsMatch\n\n  // check data matches\n  var allDataMatches = operandsMatch({\n    name: 'data',\n    fieldValue: function(field){\n      return element._private.data[field];\n    },\n    fieldRef: function(field){\n      return 'element._private.data.' + field;\n    },\n    fieldUndefined: function(field){\n      return element._private.data[field] === undefined;\n    },\n    fieldTruthy: function(field){\n      if( element._private.data[field] ){\n        return true;\n      }\n      return false;\n    }\n  });\n\n  if( !allDataMatches ){\n    return false;\n  }\n\n  // check metadata matches\n  var allMetaMatches = operandsMatch({\n    name: 'meta',\n    fieldValue: function(field){\n      return element[field]();\n    },\n    fieldRef: function(field){\n      return 'element.' + field + '()';\n    },\n    fieldUndefined: function(field){\n      return element[field]() == null;\n    },\n    fieldTruthy: function(field){\n      if( element[field]() ){\n        return true;\n      }\n      return false;\n    }\n  });\n\n  if( !allMetaMatches ){\n    return false;\n  }\n\n  // check collection\n  if( query.collection != null ){\n    var matchesAny = query.collection._private.ids[ element.id() ] != null;\n\n    if( !matchesAny ){\n      return false;\n    }\n  }\n\n  // check filter function\n  if( query.filter != null && element.collection().filter( query.filter ).size() === 0 ){\n    return false;\n  }\n\n\n  // check parent/child relations\n  var confirmRelations = function( query, elements ){\n    if( query != null ){\n      var matches = false;\n\n      if( !cy.hasCompoundNodes() ){\n        return false;\n      }\n\n      elements = elements(); // make elements functional so we save cycles if query == null\n\n      // query must match for at least one element (may be recursive)\n      for(var i = 0; i < elements.length; i++){\n        if( queryMatches( query, elements[i] ) ){\n          matches = true;\n          break;\n        }\n      }\n\n      return matches;\n    } else {\n      return true;\n    }\n  };\n\n  if (! confirmRelations(query.parent, function(){\n    return element.parent();\n  }) ){ return false; }\n\n  if (! confirmRelations(query.ancestor, function(){\n    return element.parents();\n  }) ){ return false; }\n\n  if (! confirmRelations(query.child, function(){\n    return element.children();\n  }) ){ return false; }\n\n  if (! confirmRelations(query.descendant, function(){\n    return element.descendants();\n  }) ){ return false; }\n\n  // we've reached the end, so we've matched everything for this query\n  return true;\n}; // queryMatches\n\n// filter an existing collection\nselfn.filter = function(collection){\n  var self = this;\n  var cy = collection.cy();\n\n  // don't bother trying if it's invalid\n  if( self._private.invalid ){\n    return cy.collection();\n  }\n\n  var selectorFunction = function(i, element){\n    for(var j = 0; j < self.length; j++){\n      var query = self[j];\n\n      if( queryMatches(query, element) ){\n        return true;\n      }\n    }\n\n    return false;\n  };\n\n  if( self._private.selectorText == null ){\n    selectorFunction = function(){ return true; };\n  }\n\n  var filteredCollection = collection.filter( selectorFunction );\n\n  return filteredCollection;\n}; // filter\n\n// does selector match a single element?\nselfn.matches = function(ele){\n  var self = this;\n\n  // don't bother trying if it's invalid\n  if( self._private.invalid ){\n    return false;\n  }\n\n  for(var j = 0; j < self.length; j++){\n    var query = self[j];\n\n    if( queryMatches(query, ele) ){\n      return true;\n    }\n  }\n\n  return false;\n}; // filter\n\n// ith query to string\nselfn.toString = selfn.selector = function(){\n\n  var str = '';\n\n  var clean = function(obj, isValue){\n    if( is.string(obj) ){\n      return isValue ? '\"' + obj + '\"' : obj;\n    }\n    return '';\n  };\n\n  var queryToString = function(query){\n    var str = '';\n\n    if( query.subject === query ){\n      str += '$';\n    }\n\n    var group = clean(query.group);\n    str += group.substring(0, group.length - 1);\n\n    for(var j = 0; j < query.data.length; j++){\n      var data = query.data[j];\n\n      if( data.value ){\n        str += '[' + data.field + clean(data.operator) + clean(data.value, true) + ']';\n      } else {\n        str += '[' + clean(data.operator) + data.field + ']';\n      }\n    }\n\n    for(var j = 0; j < query.meta.length; j++){\n      var meta = query.meta[j];\n      str += '[[' + meta.field + clean(meta.operator) + clean(meta.value, true) + ']]';\n    }\n\n    for(var j = 0; j < query.colonSelectors.length; j++){\n      var sel = query.colonSelectors[i];\n      str += sel;\n    }\n\n    for(var j = 0; j < query.ids.length; j++){\n      var sel = '#' + query.ids[i];\n      str += sel;\n    }\n\n    for(var j = 0; j < query.classes.length; j++){\n      var sel = '.' + query.classes[j];\n      str += sel;\n    }\n\n    if( query.parent != null ){\n      str = queryToString( query.parent ) + ' > ' + str;\n    }\n\n    if( query.ancestor != null ){\n      str = queryToString( query.ancestor ) + ' ' + str;\n    }\n\n    if( query.child != null ){\n      str += ' > ' + queryToString( query.child );\n    }\n\n    if( query.descendant != null ){\n      str += ' ' + queryToString( query.descendant );\n    }\n\n    return str;\n  };\n\n  for(var i = 0; i < this.length; i++){\n    var query = this[i];\n\n    str += queryToString( query );\n\n    if( this.length > 1 && i < this.length - 1 ){\n      str += ', ';\n    }\n  }\n\n  return str;\n};\n\nmodule.exports = Selector;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar styfn = {};\n\n// (potentially expensive calculation)\n// apply the style to the element based on\n// - its bypass\n// - what selectors match it\nstyfn.apply = function( eles ){\n  var self = this;\n\n  if( self._private.newStyle ){ // clear style caches\n    this._private.contextStyles = {};\n    this._private.propDiffs = {};\n  }\n\n  for( var ie = 0; ie < eles.length; ie++ ){\n    var ele = eles[ie];\n    var cxtMeta = self.getContextMeta( ele );\n    var cxtStyle = self.getContextStyle( cxtMeta );\n    var app = self.applyContextStyle( cxtMeta, cxtStyle, ele );\n\n    self.updateTransitions( ele, app.diffProps );\n    self.updateStyleHints( ele );\n\n  } // for elements\n\n  self._private.newStyle = false;\n};\n\nstyfn.getPropertiesDiff = function( oldCxtKey, newCxtKey ){\n  var self = this;\n  var cache = self._private.propDiffs = self._private.propDiffs || {};\n  var dualCxtKey = oldCxtKey + '-' + newCxtKey;\n  var cachedVal = cache[dualCxtKey];\n\n  if( cachedVal ){\n    return cachedVal;\n  }\n\n  var diffProps = [];\n  var addedProp = {};\n\n  for( var i = 0; i < self.length; i++ ){\n    var cxt = self[i];\n    var oldHasCxt = oldCxtKey[i] === 't';\n    var newHasCxt = newCxtKey[i] === 't';\n    var cxtHasDiffed = oldHasCxt !== newHasCxt;\n    var cxtHasMappedProps = cxt.mappedProperties.length > 0;\n\n    if( cxtHasDiffed || cxtHasMappedProps ){\n      var props;\n\n      if( cxtHasDiffed && cxtHasMappedProps ){\n        props = cxt.properties; // suffices b/c mappedProperties is a subset of properties\n      } else if( cxtHasDiffed ){\n        props = cxt.properties; // need to check them all\n      } else if( cxtHasMappedProps ){\n        props = cxt.mappedProperties; // only need to check mapped\n      }\n\n      for( var j = 0; j < props.length; j++ ){\n        var prop = props[j];\n        var name = prop.name;\n\n        // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter\n        // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result\n        // is cached)\n        var laterCxtOverrides = false;\n        for( var k = i + 1; k < self.length; k++ ){\n          var laterCxt = self[k];\n          var hasLaterCxt = newCxtKey[k] === 't';\n\n          if( !hasLaterCxt ){ continue; } // can't override unless the context is active\n\n          laterCxtOverrides = laterCxt.properties[ prop.name ] != null;\n\n          if( laterCxtOverrides ){ break; } // exit early as long as one later context overrides\n        }\n\n        if( !addedProp[name] && !laterCxtOverrides ){\n          addedProp[name] = true;\n          diffProps.push( name );\n        }\n      } // for props\n    } // if\n\n  } // for contexts\n\n  cache[ dualCxtKey ] = diffProps;\n  return diffProps;\n};\n\nstyfn.getContextMeta = function( ele ){\n  var self = this;\n  var cxtKey = '';\n  var diffProps;\n  var prevKey = ele._private.styleCxtKey || '';\n\n  if( self._private.newStyle ){\n    prevKey = ''; // since we need to apply all style if a fresh stylesheet\n  }\n\n  // get the cxt key\n  for( var i = 0; i < self.length; i++ ){\n    var context = self[i];\n    var contextSelectorMatches = context.selector && context.selector.matches( ele ); // NB: context.selector may be null for 'core'\n\n    if( contextSelectorMatches ){\n      cxtKey += 't';\n    } else {\n      cxtKey += 'f';\n    }\n  } // for context\n\n  diffProps = self.getPropertiesDiff( prevKey, cxtKey );\n\n  ele._private.styleCxtKey = cxtKey;\n\n  return {\n    key: cxtKey,\n    diffPropNames: diffProps\n  };\n};\n\n// gets a computed ele style object based on matched contexts\nstyfn.getContextStyle = function( cxtMeta ){\n  var cxtKey = cxtMeta.key;\n  var self = this;\n  var cxtStyles = this._private.contextStyles = this._private.contextStyles || {};\n\n  // if already computed style, returned cached copy\n  if( cxtStyles[cxtKey] ){ return cxtStyles[cxtKey]; }\n\n  var style = {\n    _private: {\n      key: cxtKey\n    }\n  };\n\n  for( var i = 0; i < self.length; i++ ){\n    var cxt = self[i];\n    var hasCxt = cxtKey[i] === 't';\n\n    if( !hasCxt ){ continue; }\n\n    for( var j = 0; j < cxt.properties.length; j++ ){\n      var prop = cxt.properties[j];\n      var styProp = style[ prop.name ] = prop;\n\n      styProp.context = cxt;\n    }\n  }\n\n  cxtStyles[cxtKey] = style;\n  return style;\n};\n\nstyfn.applyContextStyle = function( cxtMeta, cxtStyle, ele ){\n  var self = this;\n  var diffProps = cxtMeta.diffPropNames;\n  var retDiffProps = {};\n\n  for( var i = 0; i < diffProps.length; i++ ){\n    var diffPropName = diffProps[i];\n    var cxtProp = cxtStyle[ diffPropName ];\n    var eleProp = ele._private.style[ diffPropName ];\n\n    // save cycles when the context prop doesn't need to be applied\n    if( !cxtProp || eleProp === cxtProp ){ continue; }\n\n    var retDiffProp = retDiffProps[ diffPropName ] = {\n      prev: eleProp\n    };\n\n    self.applyParsedProperty( ele, cxtProp );\n\n    retDiffProp.next = ele._private.style[ diffPropName ];\n\n    if( retDiffProp.next && retDiffProp.next.bypass ){\n      retDiffProp.next = retDiffProp.next.bypassed;\n    }\n  }\n\n  return {\n    diffProps: retDiffProps\n  };\n};\n\nstyfn.updateStyleHints = function(ele){\n  var _p = ele._private;\n  var self = this;\n  var style = _p.style;\n\n  if( ele.removed() ){ return; }\n\n  // set whether has pie or not; for greater efficiency\n  var hasPie = false;\n  if( _p.group === 'nodes' && self._private.hasPie ){\n    for( var i = 1; i <= self.pieBackgroundN; i++ ){ // 1..N\n      var size = _p.style['pie-' + i + '-background-size'].value;\n\n      if( size > 0 ){\n        hasPie = true;\n        break;\n      }\n    }\n  }\n\n  _p.hasPie = hasPie;\n\n  var transform = style['text-transform'].strValue;\n  var content = style['label'].strValue;\n  var fStyle = style['font-style'].strValue;\n  var size = style['font-size'].pfValue + 'px';\n  var family = style['font-family'].strValue;\n  // var variant = style['font-variant'].strValue;\n  var weight = style['font-weight'].strValue;\n  var valign = style['text-valign'].strValue;\n  var halign = style['text-valign'].strValue;\n  var oWidth = style['text-outline-width'].pfValue;\n  var wrap = style['text-wrap'].strValue;\n  var wrapW = style['text-max-width'].pfValue;\n  _p.labelKey = fStyle +'$'+ size +'$'+ family +'$'+ weight +'$'+ content +'$'+ transform +'$'+ valign +'$'+ halign +'$'+ oWidth + '$' + wrap + '$' + wrapW;\n  _p.fontKey = fStyle +'$'+ weight +'$'+ size +'$'+ family;\n\n  var width = style['width'].pfValue;\n  var height = style['height'].pfValue;\n  var borderW = style['border-width'].pfValue;\n  _p.boundingBoxKey = width +'$'+ height +'$'+ borderW;\n\n  if( ele._private.group === 'edges' ){\n    var cpss = style['control-point-step-size'].pfValue;\n    var cpd = style['control-point-distances'] ? style['control-point-distances'].pfValue.join('_') : undefined;\n    var cpw = style['control-point-weights'].value.join('_');\n    var curve = style['curve-style'].strValue;\n    var sd = style['segment-distances'] ? style['segment-distances'].pfValue.join('_') : undefined;\n    var sw = style['segment-weights'].value.join('_');\n\n    _p.boundingBoxKey += '$'+ cpss +'$'+ cpd +'$'+ cpw +'$'+ sd +'$'+ sw +'$'+ curve;\n  }\n\n  _p.styleKey = Date.now();\n};\n\n// apply a property to the style (for internal use)\n// returns whether application was successful\n//\n// now, this function flattens the property, and here's how:\n//\n// for parsedProp:{ bypass: true, deleteBypass: true }\n// no property is generated, instead the bypass property in the\n// element's style is replaced by what's pointed to by the `bypassed`\n// field in the bypass property (i.e. restoring the property the\n// bypass was overriding)\n//\n// for parsedProp:{ mapped: truthy }\n// the generated flattenedProp:{ mapping: prop }\n//\n// for parsedProp:{ bypass: true }\n// the generated flattenedProp:{ bypassed: parsedProp }\nstyfn.applyParsedProperty = function( ele, parsedProp ){\n  var self = this;\n  var prop = parsedProp;\n  var style = ele._private.style;\n  var fieldVal, flatProp;\n  var types = self.types;\n  var type = self.properties[ prop.name ].type;\n  var propIsBypass = prop.bypass;\n  var origProp = style[ prop.name ];\n  var origPropIsBypass = origProp && origProp.bypass;\n  var _p = ele._private;\n\n  // can't apply auto to width or height unless it's a parent node\n  if( (parsedProp.name === 'height' || parsedProp.name === 'width') && ele.isNode() ){\n    if( parsedProp.value === 'auto' && !ele.isParent() ){\n      return false;\n    } else if( parsedProp.value !== 'auto' && ele.isParent() ){\n      prop = parsedProp = this.parse( parsedProp.name, 'auto', propIsBypass );\n    }\n  }\n\n  // check if we need to delete the current bypass\n  if( propIsBypass && prop.deleteBypass ){ // then this property is just here to indicate we need to delete\n    var currentProp = style[ prop.name ];\n\n    // can only delete if the current prop is a bypass and it points to the property it was overriding\n    if( !currentProp ){\n      return true; // property is already not defined\n    } else if( currentProp.bypass && currentProp.bypassed ){ // then replace the bypass property with the original\n\n      // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary)\n      style[ prop.name ] = currentProp.bypassed;\n      return true;\n\n    } else {\n      return false; // we're unsuccessful deleting the bypass\n    }\n  }\n\n  var printMappingErr = function(){\n    util.error('Do not assign mappings to elements without corresponding data (e.g. ele `'+ ele.id() +'` for property `'+ prop.name +'` with data field `'+ prop.field +'`); try a `['+ prop.field +']` selector to limit scope to elements with `'+ prop.field +'` defined');\n  };\n\n  // put the property in the style objects\n  switch( prop.mapped ){ // flatten the property if mapped\n  case types.mapData:\n  case types.mapLayoutData:\n  case types.mapScratch:\n\n    var isLayout = prop.mapped === types.mapLayoutData;\n    var isScratch = prop.mapped === types.mapScratch;\n\n    // flatten the field (e.g. data.foo.bar)\n    var fields = prop.field.split(\".\");\n    var fieldVal;\n\n    if( isScratch || isLayout ){\n      fieldVal = _p.scratch;\n    } else {\n      fieldVal = _p.data;\n    }\n\n    for( var i = 0; i < fields.length && fieldVal; i++ ){\n      var field = fields[i];\n      fieldVal = fieldVal[ field ];\n    }\n\n    var percent;\n    if( !is.number(fieldVal) ){ // then keep the mapping but assume 0% for now\n      percent = 0;\n    } else {\n      percent = (fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin);\n    }\n\n    // make sure to bound percent value\n    if( percent < 0 ){\n      percent = 0;\n    } else if( percent > 1 ){\n      percent = 1;\n    }\n\n    if( type.color ){\n      var r1 = prop.valueMin[0];\n      var r2 = prop.valueMax[0];\n      var g1 = prop.valueMin[1];\n      var g2 = prop.valueMax[1];\n      var b1 = prop.valueMin[2];\n      var b2 = prop.valueMax[2];\n      var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3];\n      var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3];\n\n      var clr = [\n        Math.round( r1 + (r2 - r1)*percent ),\n        Math.round( g1 + (g2 - g1)*percent ),\n        Math.round( b1 + (b2 - b1)*percent ),\n        Math.round( a1 + (a2 - a1)*percent )\n      ];\n\n      flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing\n        bypass: prop.bypass, // we're a bypass if the mapping property is a bypass\n        name: prop.name,\n        value: clr,\n        strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')'\n      };\n\n    } else if( type.number ){\n      var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent;\n      flatProp = this.parse( prop.name, calcValue, prop.bypass, true );\n\n    } else {\n      return false; // can only map to colours and numbers\n    }\n\n    if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself\n      flatProp = this.parse( prop.name, origProp.strValue, prop.bypass, true );\n    }\n\n    if( !flatProp ){ printMappingErr(); }\n    flatProp.mapping = prop; // keep a reference to the mapping\n    prop = flatProp; // the flattened (mapped) property is the one we want\n\n    break;\n\n  // direct mapping\n  case types.data:\n  case types.layoutData:\n  case types.scratch:\n    var isLayout = prop.mapped === types.layoutData;\n    var isScratch = prop.mapped === types.scratch;\n\n    // flatten the field (e.g. data.foo.bar)\n    var fields = prop.field.split(\".\");\n    var fieldVal;\n\n    if( isScratch || isLayout ){\n      fieldVal = _p.scratch;\n    } else {\n      fieldVal = _p.data;\n    }\n\n    if( fieldVal ){ for( var i = 0; i < fields.length; i++ ){\n      var field = fields[i];\n      fieldVal = fieldVal[ field ];\n    } }\n\n    flatProp = this.parse( prop.name, fieldVal, prop.bypass, true );\n\n    if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself\n      var flatPropVal = origProp ? origProp.strValue : '';\n\n      flatProp = this.parse( prop.name, flatPropVal, prop.bypass, true );\n    }\n\n    if( !flatProp ){ printMappingErr(); }\n    flatProp.mapping = prop; // keep a reference to the mapping\n    prop = flatProp; // the flattened (mapped) property is the one we want\n\n    break;\n\n  case types.fn:\n    var fn = prop.value;\n    var fnRetVal = fn( ele );\n\n    flatProp = this.parse( prop.name, fnRetVal, prop.bypass, true );\n    flatProp.mapping = prop; // keep a reference to the mapping\n    prop = flatProp; // the flattened (mapped) property is the one we want\n\n    break;\n\n  case undefined:\n    break; // just set the property\n\n  default:\n    return false; // not a valid mapping\n  }\n\n  // if the property is a bypass property, then link the resultant property to the original one\n  if( propIsBypass ){\n    if( origPropIsBypass ){ // then this bypass overrides the existing one\n      prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass\n    } else { // then link the orig prop to the new bypass\n      prop.bypassed = origProp;\n    }\n\n    style[ prop.name ] = prop; // and set\n\n  } else { // prop is not bypass\n    if( origPropIsBypass ){ // then keep the orig prop (since it's a bypass) and link to the new prop\n      origProp.bypassed = prop;\n    } else { // then just replace the old prop with the new one\n      style[ prop.name ] = prop;\n    }\n  }\n\n  return true;\n};\n\n// updates the visual style for all elements (useful for manual style modification after init)\nstyfn.update = function(){\n  var cy = this._private.cy;\n  var eles = cy.elements();\n\n  eles.updateStyle();\n};\n\n// just update the functional properties (i.e. mappings) in the elements'\n// styles (less expensive than recalculation)\nstyfn.updateMappers = function( eles ){\n  var self = this;\n\n  for( var i = 0; i < eles.length; i++ ){ // for each ele\n    var ele = eles[i];\n    var style = ele._private.style;\n\n    for( var j = 0; j < self.properties.length; j++ ){ // for each prop\n      var prop = self.properties[j];\n      var propInStyle = style[ prop.name ];\n\n      if( propInStyle && propInStyle.mapping ){\n        var mapping = propInStyle.mapping;\n        this.applyParsedProperty( ele, mapping ); // reapply the mapping property\n      }\n    }\n\n    this.updateStyleHints( ele );\n  }\n};\n\n// diffProps : { name => { prev, next } }\nstyfn.updateTransitions = function( ele, diffProps, isBypass ){\n  var self = this;\n  var _p = ele._private;\n  var style = _p.style;\n  var props = style['transition-property'].value;\n  var duration = style['transition-duration'].pfValue;\n  var delay = style['transition-delay'].pfValue;\n  var css = {};\n\n  if( props.length > 0 && duration > 0 ){\n\n    // build up the style to animate towards\n    var anyPrev = false;\n    for( var i = 0; i < props.length; i++ ){\n      var prop = props[i];\n      var styProp = style[ prop ];\n      var diffProp = diffProps[ prop ];\n\n      if( !diffProp ){ continue; }\n\n      var prevProp = diffProp.prev;\n      var fromProp = prevProp;\n      var toProp = diffProp.next != null ? diffProp.next : styProp;\n      var diff = false;\n      var initVal;\n      var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity)\n\n      if( !fromProp ){ continue; }\n\n      // consider px values\n      if( is.number( fromProp.pfValue ) && is.number( toProp.pfValue ) ){\n        diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy\n        initVal = fromProp.pfValue + initDt * diff;\n\n      // consider numerical values\n      } else if( is.number( fromProp.value ) && is.number( toProp.value ) ){\n        diff = toProp.value - fromProp.value; // nonzero is truthy\n        initVal = fromProp.value + initDt * diff;\n\n      // consider colour values\n      } else if( is.array( fromProp.value ) && is.array( toProp.value ) ){\n        diff = fromProp.value[0] !== toProp.value[0]\n          || fromProp.value[1] !== toProp.value[1]\n          || fromProp.value[2] !== toProp.value[2]\n        ;\n\n        initVal = fromProp.strValue;\n      }\n\n      // the previous value is good for an animation only if it's different\n      if( diff ){\n        css[ prop ] = toProp.strValue; // to val\n        this.applyBypass( ele, prop, initVal ); // from val\n        anyPrev = true;\n      }\n\n    } // end if props allow ani\n\n    // can't transition if there's nothing previous to transition from\n    if( !anyPrev ){ return; }\n\n    _p.transitioning = true;\n\n    ele.stop();\n\n    if( delay > 0 ){\n      ele.delay( delay );\n    }\n\n    ele.animate({\n      css: css\n    }, {\n      duration: duration,\n      easing: style['transition-timing-function'].value,\n      queue: false,\n      complete: function(){\n        if( !isBypass ){\n          self.removeBypasses( ele, props );\n        }\n\n        _p.transitioning = false;\n      }\n    });\n\n  } else if( _p.transitioning ){\n    ele.stop();\n\n    this.removeBypasses( ele, props );\n\n    _p.transitioning = false;\n  }\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\n\nvar styfn = {};\n\n// bypasses are applied to an existing style on an element, and just tacked on temporarily\n// returns true iff application was successful for at least 1 specified property\nstyfn.applyBypass = function( eles, name, value, updateTransitions ){\n  var self = this;\n  var props = [];\n  var isBypass = true;\n\n  // put all the properties (can specify one or many) in an array after parsing them\n  if( name === \"*\" || name === \"**\" ){ // apply to all property names\n\n    if( value !== undefined ){\n      for( var i = 0; i < self.properties.length; i++ ){\n        var prop = self.properties[i];\n        var name = prop.name;\n\n        var parsedProp = this.parse(name, value, true);\n\n        if( parsedProp ){\n          props.push( parsedProp );\n        }\n      }\n    }\n\n  } else if( is.string(name) ){ // then parse the single property\n    var parsedProp = this.parse(name, value, true);\n\n    if( parsedProp ){\n      props.push( parsedProp );\n    }\n  } else if( is.plainObject(name) ){ // then parse each property\n    var specifiedProps = name;\n    updateTransitions = value;\n\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var name = prop.name;\n      var value = specifiedProps[ name ];\n\n      if( value === undefined ){ // try camel case name too\n        value = specifiedProps[ util.dash2camel(name) ];\n      }\n\n      if( value !== undefined ){\n        var parsedProp = this.parse(name, value, true);\n\n        if( parsedProp ){\n          props.push( parsedProp );\n        }\n      }\n    }\n  } else { // can't do anything without well defined properties\n    return false;\n  }\n\n  // we've failed if there are no valid properties\n  if( props.length === 0 ){ return false; }\n\n  // now, apply the bypass properties on the elements\n  var ret = false; // return true if at least one succesful bypass applied\n  for( var i = 0; i < eles.length; i++ ){ // for each ele\n    var ele = eles[i];\n    var style = ele._private.style;\n    var diffProps = {};\n    var diffProp;\n\n    for( var j = 0; j < props.length; j++ ){ // for each prop\n      var prop = props[j];\n\n      if( updateTransitions ){\n        var prevProp = style[ prop.name ];\n        diffProp = diffProps[ prop.name ] = { prev: prevProp };\n      }\n\n      ret = this.applyParsedProperty( ele, prop ) || ret;\n\n      if( updateTransitions ){\n        diffProp.next = style[ prop.name ];\n      }\n\n    } // for props\n\n    if( ret ){\n      this.updateStyleHints( ele );\n    }\n\n    if( updateTransitions ){\n      this.updateTransitions( ele, diffProps, isBypass );\n    }\n  } // for eles\n\n  return ret;\n};\n\n// only useful in specific cases like animation\nstyfn.overrideBypass = function( eles, name, value ){\n  name = util.camel2dash(name);\n\n  for( var i = 0; i < eles.length; i++ ){\n    var ele = eles[i];\n    var prop = ele._private.style[ name ];\n    var type = this.properties[ name ].type;\n    var isColor = type.color;\n    var isMulti = type.mutiple;\n\n    if( !prop.bypass ){ // need a bypass if one doesn't exist\n      this.applyBypass( ele, name, value );\n      continue;\n    }\n\n    prop.value = value;\n\n    if( prop.pfValue != null ){\n      prop.pfValue = value;\n    }\n\n    if( isColor ){\n      prop.strValue = 'rgb(' + value.join(',') + ')';\n    } else if( isMulti ){\n      prop.strValue = value.join(' ');\n    } else {\n      prop.strValue = '' + value;\n    }\n  }\n};\n\nstyfn.removeAllBypasses = function( eles, updateTransitions ){\n  return this.removeBypasses( eles, this.propertyNames, updateTransitions );\n};\n\nstyfn.removeBypasses = function( eles, props, updateTransitions ){\n  var isBypass = true;\n\n  for( var j = 0; j < eles.length; j++ ){\n    var ele = eles[j];\n    var diffProps = {};\n    var style = ele._private.style;\n\n    for( var i = 0; i < props.length; i++ ){\n      var name = props[i];\n      var prop = this.properties[ name ];\n      var value = ''; // empty => remove bypass\n      var parsedProp = this.parse(name, value, true);\n      var prevProp = style[ prop.name ];\n      var diffProp = diffProps[ prop.name ] = { prev: prevProp };\n\n      this.applyParsedProperty(ele, parsedProp);\n\n      diffProp.next = style[ prop.name ];\n    } // for props\n\n    this.updateStyleHints( ele );\n\n    if( updateTransitions ){\n      this.updateTransitions( ele, diffProps, isBypass );\n    }\n  } // for eles\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar window = require('../window');\n\nvar styfn = {};\n\n// gets what an em size corresponds to in pixels relative to a dom element\nstyfn.getEmSizeInPixels = function(){\n  var px = this.containerCss('font-size');\n\n  if( px != null ){\n    return parseFloat( px );\n  } else {\n    return 1; // for headless\n  }\n};\n\n// gets css property from the core container\nstyfn.containerCss = function( propName ){\n  var cy = this._private.cy;\n  var domElement = cy.container();\n\n  if( window && domElement && window.getComputedStyle ){\n    return window.getComputedStyle(domElement).getPropertyValue( propName );\n  }\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar styfn = {};\n\n// gets the rendered style for an element\nstyfn.getRenderedStyle = function( ele ){\n  return this.getRawStyle( ele, true );\n};\n\n// gets the raw style for an element\nstyfn.getRawStyle = function( ele, isRenderedVal ){\n  var self = this;\n  var ele = ele[0]; // insure it's an element\n\n  if( ele ){\n    var rstyle = {};\n\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var val = self.getStylePropertyValue( ele, prop.name, isRenderedVal );\n\n      if( val ){\n        rstyle[ prop.name ] = val;\n        rstyle[ util.dash2camel(prop.name) ] = val;\n      }\n    }\n\n    return rstyle;\n  }\n};\n\nstyfn.getStylePropertyValue = function( ele, propName, isRenderedVal ){\n  var self = this;\n  var ele = ele[0]; // insure it's an element\n\n  if( ele ){\n    var style = ele._private.style;\n    var prop = self.properties[ propName ];\n    var type = prop.type;\n    var styleProp = style[ prop.name ];\n    var zoom = ele.cy().zoom();\n\n    if( styleProp ){\n      var units = styleProp.units ? type.implicitUnits || 'px' : null;\n      var val = units ? [].concat( styleProp.pfValue ).map(function( pfValue ){\n        return ( pfValue * (isRenderedVal ? zoom : 1) ) + units;\n      }).join(' ') : styleProp.strValue;\n\n      return val;\n    }\n  }\n};\n\n// gets the value style for an element (useful for things like animations)\nstyfn.getValueStyle = function( ele ){\n  var self = this;\n  var rstyle = {};\n  var style;\n  var isEle = is.element(ele);\n\n  if( isEle ){\n    style = ele._private.style;\n  } else {\n    style = ele; // just passed the style itself\n  }\n\n  if( style ){\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var styleProp = style[ prop.name ] || style[ util.dash2camel(prop.name) ];\n\n      if( styleProp !== undefined ){ // then make a prop of it\n        if( is.plainObject( styleProp ) ){\n          styleProp = this.parse( prop.name, styleProp.strValue );\n        } else {\n          styleProp = this.parse( prop.name, styleProp );\n        }\n      }\n\n      if( styleProp ){\n        rstyle[ prop.name ] = styleProp;\n        rstyle[ util.dash2camel(prop.name) ] = styleProp;\n      }\n    }\n  }\n\n  return rstyle;\n};\n\nstyfn.getPropsList = function( propsObj ){\n  var self = this;\n  var rstyle = [];\n  var style = propsObj;\n  var props = self.properties;\n\n  if( style ){\n    for( var name in style ){\n      var val = style[name];\n      var prop = props[name] || props[ util.camel2dash(name) ];\n      var styleProp = this.parse( prop.name, val );\n\n      rstyle.push( styleProp );\n    }\n  }\n\n  return rstyle;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\nvar Selector = require('../selector');\n\nvar Style = function( cy ){\n\n  if( !(this instanceof Style) ){\n    return new Style(cy);\n  }\n\n  if( !is.core(cy) ){\n    util.error('A style must have a core reference');\n    return;\n  }\n\n  this._private = {\n    cy: cy,\n    coreStyle: {},\n    newStyle: true\n  };\n\n  this.length = 0;\n\n  this.addDefaultStylesheet();\n};\n\nvar styfn = Style.prototype;\n\nstyfn.instanceString = function(){\n  return 'style';\n};\n\n// remove all contexts\nstyfn.clear = function(){\n  for( var i = 0; i < this.length; i++ ){\n    this[i] = undefined;\n  }\n  this.length = 0;\n  this._private.newStyle = true;\n\n  return this; // chaining\n};\n\nstyfn.resetToDefault = function(){\n  this.clear();\n  this.addDefaultStylesheet();\n\n  return this;\n};\n\n// builds a style object for the 'core' selector\nstyfn.core = function(){\n  return this._private.coreStyle;\n};\n\n// create a new context from the specified selector string and switch to that context\nstyfn.selector = function( selectorStr ){\n  // 'core' is a special case and does not need a selector\n  var selector = selectorStr === 'core' ? null : new Selector( selectorStr );\n\n  var i = this.length++; // new context means new index\n  this[i] = {\n    selector: selector,\n    properties: [],\n    mappedProperties: [],\n    index: i\n  };\n\n  return this; // chaining\n};\n\n// add one or many css rules to the current context\nstyfn.css = function(){\n  var self = this;\n  var args = arguments;\n\n  switch( args.length ){\n  case 1:\n    var map = args[0];\n\n    for( var i = 0; i < self.properties.length; i++ ){\n      var prop = self.properties[i];\n      var mapVal = map[ prop.name ];\n\n      if( mapVal === undefined ){\n        mapVal = map[ util.dash2camel(prop.name) ];\n      }\n\n      if( mapVal !== undefined ){\n        this.cssRule( prop.name, mapVal );\n      }\n    }\n\n    break;\n\n  case 2:\n    this.cssRule( args[0], args[1] );\n    break;\n\n  default:\n    break; // do nothing if args are invalid\n  }\n\n  return this; // chaining\n};\nstyfn.style = styfn.css;\n\n// add a single css rule to the current context\nstyfn.cssRule = function( name, value ){\n  // name-value pair\n  var property = this.parse( name, value );\n\n  // add property to current context if valid\n  if( property ){\n    var i = this.length - 1;\n    this[i].properties.push( property );\n    this[i].properties[ property.name ] = property; // allow access by name as well\n\n    if( property.name.match(/pie-(\\d+)-background-size/) && property.value ){\n      this._private.hasPie = true;\n    }\n\n    if( property.mapped ){\n      this[i].mappedProperties.push( property );\n    }\n\n    // add to core style if necessary\n    var currentSelectorIsCore = !this[i].selector;\n    if( currentSelectorIsCore ){\n      this._private.coreStyle[ property.name ] = property;\n    }\n  }\n\n  return this; // chaining\n};\n\n// static function\nStyle.fromJson = function( cy, json ){\n  var style = new Style( cy );\n\n  style.fromJson( json );\n\n  return style;\n};\n\nStyle.fromString = function( cy, string ){\n  return new Style( cy ).fromString( string );\n};\n\n[\n  require('./apply'),\n  require('./bypass'),\n  require('./container'),\n  require('./get-for-ele'),\n  require('./json'),\n  require('./string-sheet'),\n  require('./properties'),\n  require('./parse')\n].forEach(function( props ){\n  util.extend( styfn, props );\n});\n\n\nStyle.types = styfn.types;\nStyle.properties = styfn.properties;\n\nmodule.exports = Style;\n","'use strict';\n\nvar styfn = {};\n\nstyfn.applyFromJson = function( json ){\n  var style = this;\n\n  for( var i = 0; i < json.length; i++ ){\n    var context = json[i];\n    var selector = context.selector;\n    var props = context.style || context.css;\n\n    style.selector( selector ); // apply selector\n\n    for( var name in props ){\n      var value = props[name];\n\n      style.css( name, value ); // apply property\n    }\n  }\n\n  return style;\n};\n\n// accessible cy.style() function\nstyfn.fromJson = function( json ){\n  var style = this;\n\n  style.resetToDefault();\n  style.applyFromJson( json );\n\n  return style;\n};\n\n// get json from cy.style() api\nstyfn.json = function(){\n  var json = [];\n\n  for( var i = this.defaultLength; i < this.length; i++ ){\n    var cxt = this[i];\n    var selector = cxt.selector;\n    var props = cxt.properties;\n    var css = {};\n\n    for( var j = 0; j < props.length; j++ ){\n      var prop = props[j];\n      css[ prop.name ] = prop.strValue;\n    }\n\n    json.push({\n      selector: !selector ? 'core' : selector.toString(),\n      style: css\n    });\n  }\n\n  return json;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar styfn = {};\n\n// a caching layer for property parsing\nstyfn.parse = function( name, value, propIsBypass, propIsFlat ){\n  var argHash = [ name, value, propIsBypass, propIsFlat ].join('$');\n  var propCache = this.propCache = this.propCache || {};\n  var ret;\n  var impl = parseImpl.bind( this );\n\n  if( !(ret = propCache[argHash]) ){\n    ret = propCache[argHash] = impl( name, value, propIsBypass, propIsFlat );\n  }\n\n  // always need a copy since props are mutated later in their lifecycles\n  ret = util.copy( ret );\n\n  if( ret ){\n    ret.value = util.copy( ret.value ); // because it could be an array, e.g. colour\n  }\n\n  return ret;\n};\n\n// parse a property; return null on invalid; return parsed property otherwise\n// fields :\n// - name : the name of the property\n// - value : the parsed, native-typed value of the property\n// - strValue : a string value that represents the property value in valid css\n// - bypass : true iff the property is a bypass property\nvar parseImpl = function( name, value, propIsBypass, propIsFlat ){\n  var self = this;\n\n  name = util.camel2dash( name ); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName')\n\n  var property = self.properties[ name ];\n  var passedValue = value;\n  var types = self.types;\n\n  if( !property ){ return null; } // return null on property of unknown name\n  if( value === undefined || value === null ){ return null; } // can't assign null\n\n  // the property may be an alias\n  if( property.alias ){\n    property = property.pointsTo;\n    name = property.name;\n  }\n\n  var valueIsString = is.string(value);\n  if( valueIsString ){ // trim the value to make parsing easier\n    value = value.trim();\n  }\n\n  var type = property.type;\n  if( !type ){ return null; } // no type, no luck\n\n  // check if bypass is null or empty string (i.e. indication to delete bypass property)\n  if( propIsBypass && (value === '' || value === null) ){\n    return {\n      name: name,\n      value: value,\n      bypass: true,\n      deleteBypass: true\n    };\n  }\n\n  // check if value is a function used as a mapper\n  if( is.fn(value) ){\n    return {\n      name: name,\n      value: value,\n      strValue: 'fn',\n      mapped: types.fn,\n      bypass: propIsBypass\n    };\n  }\n\n  // check if value is mapped\n  var data, mapData, layoutData, mapLayoutData, scratch, mapScratch;\n  if( !valueIsString || propIsFlat ){\n    // then don't bother to do the expensive regex checks\n\n  } else if(\n    ( data = new RegExp( types.data.regex ).exec( value ) ) ||\n    ( layoutData = new RegExp( types.layoutData.regex ).exec( value ) ) ||\n    ( scratch = new RegExp( types.scratch.regex ).exec( value ) )\n  ){\n    if( propIsBypass ){ return false; } // mappers not allowed in bypass\n\n    var mapped;\n    if( data ){\n      mapped = types.data;\n    } else if( layoutData ){\n      mapped = types.layoutData;\n    } else {\n      mapped = types.scratch;\n    }\n\n    data = data || layoutData || scratch;\n\n    return {\n      name: name,\n      value: data,\n      strValue: '' + value,\n      mapped: mapped,\n      field: data[1],\n      bypass: propIsBypass\n    };\n\n  } else if(\n    ( mapData = new RegExp( types.mapData.regex ).exec( value ) ) ||\n    ( mapLayoutData = new RegExp( types.mapLayoutData.regex ).exec( value ) ) ||\n    ( mapScratch = new RegExp( types.mapScratch.regex ).exec( value ) )\n  ){\n    if( propIsBypass ){ return false; } // mappers not allowed in bypass\n    if( type.multiple ){ return false; } // impossible to map to num\n\n    var mapped;\n    if( mapData ){\n      mapped = types.mapData;\n    } else if( mapLayoutData ){\n      mapped = types.mapLayoutData;\n    } else {\n      mapped = types.mapScratch;\n    }\n\n    mapData = mapData || mapLayoutData || mapScratch;\n\n    // we can map only if the type is a colour or a number\n    if( !(type.color || type.number) ){ return false; }\n\n    var valueMin = this.parse( name, mapData[4] ); // parse to validate\n    if( !valueMin || valueMin.mapped ){ return false; } // can't be invalid or mapped\n\n    var valueMax = this.parse( name, mapData[5] ); // parse to validate\n    if( !valueMax || valueMax.mapped ){ return false; } // can't be invalid or mapped\n\n    // check if valueMin and valueMax are the same\n    if( valueMin.value === valueMax.value ){\n      return false; // can't make much of a mapper without a range\n\n    } else if( type.color ){\n      var c1 = valueMin.value;\n      var c2 = valueMax.value;\n\n      var same = c1[0] === c2[0] // red\n        && c1[1] === c2[1] // green\n        && c1[2] === c2[2] // blue\n        && ( // optional alpha\n          c1[3] === c2[3] // same alpha outright\n          || (\n            (c1[3] == null || c1[3] === 1) // full opacity for colour 1?\n            &&\n            (c2[3] == null || c2[3] === 1) // full opacity for colour 2?\n          )\n        )\n      ;\n\n      if( same ){ return false; } // can't make a mapper without a range\n    }\n\n    return {\n      name: name,\n      value: mapData,\n      strValue: '' + value,\n      mapped: mapped,\n      field: mapData[1],\n      fieldMin: parseFloat( mapData[2] ), // min & max are numeric\n      fieldMax: parseFloat( mapData[3] ),\n      valueMin: valueMin.value,\n      valueMax: valueMax.value,\n      bypass: propIsBypass\n    };\n  }\n\n  if( type.multiple && propIsFlat !== 'multiple' ){\n    var vals;\n\n    if( valueIsString ){\n      vals = value.split(/\\s+/);\n    } else if( is.array(value) ){\n      vals = value;\n    } else {\n      vals = [ value ];\n    }\n\n    if( type.evenMultiple && vals.length % 2 !== 0 ){ return null; }\n\n    var valArr = vals.map(function( v ){\n      var p = self.parse( name, v, propIsBypass, 'multiple' );\n\n      if( p.pfValue != null ){\n        return p.pfValue;\n      } else {\n        return p.value;\n      }\n    });\n\n    return {\n      name: name,\n      value: valArr,\n      pfValue: valArr,\n      strValue: valArr.join(' '),\n      bypass: propIsBypass,\n      units: type.number && !type.unitless ? type.implicitUnits || 'px' : undefined\n    };\n  }\n\n  // several types also allow enums\n  var checkEnums = function(){\n    for( var i = 0; i < type.enums.length; i++ ){\n      var en = type.enums[i];\n\n      if( en === value ){\n        return {\n          name: name,\n          value: value,\n          strValue: '' + value,\n          bypass: propIsBypass\n        };\n      }\n    }\n\n    return null;\n  };\n\n  // check the type and return the appropriate object\n  if( type.number ){\n    var units;\n    var implicitUnits = 'px'; // not set => px\n\n    if( type.units ){ // use specified units if set\n      units = type.units;\n    }\n\n    if( type.implicitUnits ){\n      implicitUnits = type.implicitUnits;\n    }\n\n    if( !type.unitless ){\n      if( valueIsString ){\n        var unitsRegex = 'px|em' + (type.allowPercent ? '|\\\\%' : '');\n        if( units ){ unitsRegex = units; } // only allow explicit units if so set\n        var match = value.match( '^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$' );\n\n        if( match ){\n          value = match[1];\n          units = match[2] || implicitUnits;\n        }\n\n      } else if( !units || type.implicitUnits ) {\n        units = implicitUnits; // implicitly px if unspecified\n      }\n    }\n\n    value = parseFloat( value );\n\n    // if not a number and enums not allowed, then the value is invalid\n    if( isNaN(value) && type.enums === undefined ){\n      return null;\n    }\n\n    // check if this number type also accepts special keywords in place of numbers\n    // (i.e. `left`, `auto`, etc)\n    if( isNaN(value) && type.enums !== undefined ){\n      value = passedValue;\n\n      return checkEnums();\n    }\n\n    // check if value must be an integer\n    if( type.integer && !is.integer(value) ){\n      return null;\n    }\n\n    // check value is within range\n    if( (type.min !== undefined && value < type.min)\n    || (type.max !== undefined && value > type.max)\n    ){\n      return null;\n    }\n\n    var ret = {\n      name: name,\n      value: value,\n      strValue: '' + value + (units ? units : ''),\n      units: units,\n      bypass: propIsBypass\n    };\n\n    // normalise value in pixels\n    if( type.unitless || (units !== 'px' && units !== 'em') ){\n      ret.pfValue = value;\n    } else {\n      ret.pfValue = ( units === 'px' || !units ? (value) : (this.getEmSizeInPixels() * value) );\n    }\n\n    // normalise value in ms\n    if( units === 'ms' || units === 's' ){\n      ret.pfValue = units === 'ms' ? value : 1000 * value;\n    }\n\n    // normalise value in rad\n    if( units === 'deg' || units === 'rad' ){\n      ret.pfValue = units === 'rad' ? value : value * Math.PI/180;\n    }\n\n    return ret;\n\n  } else if( type.propList ) {\n\n    var props = [];\n    var propsStr = '' + value;\n\n    if( propsStr === 'none' ){\n      // leave empty\n\n    } else { // go over each prop\n\n      var propsSplit = propsStr.split(',');\n      for( var i = 0; i < propsSplit.length; i++ ){\n        var propName = propsSplit[i].trim();\n\n        if( self.properties[propName] ){\n          props.push( propName );\n        }\n      }\n\n      if( props.length === 0 ){ return null; }\n    }\n\n    return {\n      name: name,\n      value: props,\n      strValue: props.length === 0 ? 'none' : props.join(', '),\n      bypass: propIsBypass\n    };\n\n  } else if( type.color ){\n    var tuple = util.color2tuple( value );\n\n    if( !tuple ){ return null; }\n\n    return {\n      name: name,\n      value: tuple,\n      strValue: '' + value,\n      bypass: propIsBypass,\n      roundValue: true\n    };\n\n  } else if( type.regex || type.regexes ){\n\n    // first check enums\n    if( type.enums ){\n      var enumProp = checkEnums();\n\n      if( enumProp ){ return enumProp; }\n    }\n\n    var regexes = type.regexes ? type.regexes : [ type.regex ];\n\n    for( var i = 0; i < regexes.length; i++ ){\n      var regex = new RegExp( regexes[i] ); // make a regex from the type string\n      var m = regex.exec( value );\n\n      if( m ){ // regex matches\n        return {\n          name: name,\n          value: m,\n          strValue: '' + value,\n          bypass: propIsBypass\n        };\n\n      }\n    }\n\n    return null; // didn't match any\n\n  } else if( type.string ){\n    // just return\n    return {\n      name: name,\n      value: value,\n      strValue: '' + value,\n      bypass: propIsBypass\n    };\n\n  } else if( type.enums ){ // check enums last because it's a combo type in others\n    return checkEnums();\n\n  } else {\n    return null; // not a type we can handle\n  }\n\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\n\nvar styfn = {};\n\n(function(){\n  var number = util.regex.number;\n  var rgba = util.regex.rgbaNoBackRefs;\n  var hsla = util.regex.hslaNoBackRefs;\n  var hex3 = util.regex.hex3;\n  var hex6 = util.regex.hex6;\n  var data = function( prefix ){ return '^' + prefix + '\\\\s*\\\\(\\\\s*([\\\\w\\\\.]+)\\\\s*\\\\)$'; };\n  var mapData = function( prefix ){\n    var mapArg = number + '|\\\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6;\n    return '^' + prefix + '\\\\s*\\\\(([\\\\w\\\\.]+)\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + mapArg + ')\\\\s*\\\\,\\\\s*(' + mapArg + ')\\\\)$';\n  };\n\n  // each visual style property has a type and needs to be validated according to it\n  styfn.types = {\n    time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' },\n    percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' },\n    zeroOneNumber: { number: true, min: 0, max: 1, unitless: true },\n    nOneOneNumber: { number: true, min: -1, max: 1, unitless: true },\n    nonNegativeInt: { number: true, min: 0, integer: true, unitless: true },\n    position: { enums: ['parent', 'origin'] },\n    nodeSize: { number: true, min: 0, enums: ['auto', 'label'] },\n    number: { number: true, unitless: true },\n    numbers: { number: true, unitless: true, multiple: true },\n    size: { number: true, min: 0 },\n    bidirectionalSize: { number: true }, // allows negative\n    bidirectionalSizes: { number: true, multiple: true }, // allows negative\n    bgSize: { number: true, min: 0, allowPercent: true },\n    bgWH: { number: true, min: 0, allowPercent: true, enums: ['auto'] },\n    bgPos: { number: true, allowPercent: true },\n    bgRepeat: { enums: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'] },\n    bgFit: { enums: ['none', 'contain', 'cover'] },\n    bgClip: { enums: ['none', 'node'] },\n    color: { color: true },\n    bool: { enums: ['yes', 'no'] },\n    lineStyle: { enums: ['solid', 'dotted', 'dashed'] },\n    borderStyle: { enums: ['solid', 'dotted', 'dashed', 'double'] },\n    curveStyle: { enums: ['bezier', 'unbundled-bezier', 'haystack', 'segments'] },\n    fontFamily: { regex: '^([\\\\w- \\\\\"]+(?:\\\\s*,\\\\s*[\\\\w- \\\\\"]+)*)$' },\n    fontVariant: { enums: ['small-caps', 'normal'] },\n    fontStyle: { enums: ['italic', 'normal', 'oblique'] },\n    fontWeight: { enums: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900] },\n    textDecoration: { enums: ['none', 'underline', 'overline', 'line-through'] },\n    textTransform: { enums: ['none', 'uppercase', 'lowercase'] },\n    textWrap: { enums: ['none', 'wrap'] },\n    textBackgroundShape: { enums: ['rectangle', 'roundrectangle']},\n    nodeShape: { enums: ['rectangle', 'roundrectangle', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'diamond', 'vee', 'rhomboid', 'polygon'] },\n    compoundIncludeLabels: { enums: ['include', 'exclude'] },\n    arrowShape: { enums: ['tee', 'triangle', 'triangle-tee', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none'] },\n    arrowFill: { enums: ['filled', 'hollow'] },\n    display: { enums: ['element', 'none'] },\n    visibility: { enums: ['hidden', 'visible'] },\n    valign: { enums: ['top', 'center', 'bottom'] },\n    halign: { enums: ['left', 'center', 'right'] },\n    text: { string: true },\n    data: { mapping: true, regex: data('data') },\n    layoutData: { mapping: true, regex: data('layoutData') },\n    scratch: { mapping: true, regex: data('scratch') },\n    mapData: { mapping: true, regex: mapData('mapData') },\n    mapLayoutData: { mapping: true, regex: mapData('mapLayoutData') },\n    mapScratch: { mapping: true, regex: mapData('mapScratch') },\n    fn: { mapping: true, fn: true },\n    url: { regex: '^url\\\\s*\\\\(\\\\s*([^\\\\s]+)\\\\s*\\\\s*\\\\)|none|(.+)$' },\n    propList: { propList: true },\n    angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' },\n    textRotation: { enums: ['none', 'autorotate'] },\n    polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true },\n    easing: {\n      regexes: [\n        '^(spring)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$',\n        '^(cubic-bezier)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$'\n      ],\n      enums: [\n        'linear',\n        'ease', 'ease-in', 'ease-out', 'ease-in-out',\n        'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine',\n        'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad',\n        'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic',\n        'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart',\n        'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint',\n        'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo',\n        'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ'\n      ]\n    }\n  };\n\n  // define visual style properties\n  var t = styfn.types;\n  var props = styfn.properties = [\n    // labels\n    { name: 'text-valign', type: t.valign },\n    { name: 'text-halign', type: t.halign },\n    { name: 'color', type: t.color },\n    { name: 'label', type: t.text },\n    { name: 'text-outline-color', type: t.color },\n    { name: 'text-outline-width', type: t.size },\n    { name: 'text-outline-opacity', type: t.zeroOneNumber },\n    { name: 'text-opacity', type: t.zeroOneNumber },\n    { name: 'text-background-color', type: t.color },\n    { name: 'text-background-opacity', type: t.zeroOneNumber },\n    { name: 'text-border-opacity', type: t.zeroOneNumber },\n    { name: 'text-border-color', type: t.color },\n    { name: 'text-border-width', type: t.size },\n    { name: 'text-border-style', type: t.borderStyle },\n    { name: 'text-background-shape', type: t.textBackgroundShape},\n    // { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas\n    { name: 'text-transform', type: t.textTransform },\n    { name: 'text-wrap', type: t.textWrap },\n    { name: 'text-max-width', type: t.size },\n    { name: 'text-events', type: t.bool },\n\n    // { name: 'text-rotation', type: t.angle }, // TODO disabled b/c rotation breaks bounding boxes\n    { name: 'font-family', type: t.fontFamily },\n    { name: 'font-style', type: t.fontStyle },\n    // { name: 'font-variant', type: t.fontVariant }, // not useful\n    { name: 'font-weight', type: t.fontWeight },\n    { name: 'font-size', type: t.size },\n    { name: 'min-zoomed-font-size', type: t.size },\n    { name: 'edge-text-rotation', type: t.textRotation },\n\n    // behaviour\n    { name: 'events', type: t.bool },\n\n    // visibility\n    { name: 'display', type: t.display },\n    { name: 'visibility', type: t.visibility },\n    { name: 'opacity', type: t.zeroOneNumber },\n    { name: 'z-index', type: t.nonNegativeInt },\n\n    // overlays\n    { name: 'overlay-padding', type: t.size },\n    { name: 'overlay-color', type: t.color },\n    { name: 'overlay-opacity', type: t.zeroOneNumber },\n\n    // shadows\n    { name: 'shadow-blur', type: t.size },\n    { name: 'shadow-color', type: t.color },\n    { name: 'shadow-opacity', type: t.zeroOneNumber },\n    { name: 'shadow-offset-x', type: t.bidirectionalSize },\n    { name: 'shadow-offset-y', type: t.bidirectionalSize },\n\n    // label shadows\n    { name: 'text-shadow-blur', type: t.size },\n    { name: 'text-shadow-color', type: t.color },\n    { name: 'text-shadow-opacity', type: t.zeroOneNumber },\n    { name: 'text-shadow-offset-x', type: t.bidirectionalSize },\n    { name: 'text-shadow-offset-y', type: t.bidirectionalSize },\n\n    // transition anis\n    { name: 'transition-property', type: t.propList },\n    { name: 'transition-duration', type: t.time },\n    { name: 'transition-delay', type: t.time },\n    { name: 'transition-timing-function', type: t.easing },\n\n    // node body\n    { name: 'height', type: t.nodeSize },\n    { name: 'width', type: t.nodeSize },\n    { name: 'shape', type: t.nodeShape },\n    { name: 'shape-polygon-points', type: t.polygonPointList },\n    { name: 'background-color', type: t.color },\n    { name: 'background-opacity', type: t.zeroOneNumber },\n    { name: 'background-blacken', type: t.nOneOneNumber },\n    { name: 'padding-left', type: t.size },\n    { name: 'padding-right', type: t.size },\n    { name: 'padding-top', type: t.size },\n    { name: 'padding-bottom', type: t.size },\n\n    // node border\n    { name: 'border-color', type: t.color },\n    { name: 'border-opacity', type: t.zeroOneNumber },\n    { name: 'border-width', type: t.size },\n    { name: 'border-style', type: t.borderStyle },\n\n    // node background images\n    { name: 'background-image', type: t.url },\n    { name: 'background-image-opacity', type: t.zeroOneNumber },\n    { name: 'background-position-x', type: t.bgPos },\n    { name: 'background-position-y', type: t.bgPos },\n    { name: 'background-repeat', type: t.bgRepeat },\n    { name: 'background-fit', type: t.bgFit },\n    { name: 'background-clip', type: t.bgClip },\n    { name: 'background-width', type: t.bgWH },\n    { name: 'background-height', type: t.bgWH },\n\n    // compound props\n    { name: 'position', type: t.position },\n    { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels },\n\n    // edge line\n    { name: 'line-style', type: t.lineStyle },\n    { name: 'line-color', type: t.color },\n    { name: 'curve-style', type: t.curveStyle },\n    { name: 'haystack-radius', type: t.zeroOneNumber },\n    { name: 'control-point-step-size', type: t.size },\n    { name: 'control-point-distances', type: t.bidirectionalSizes },\n    { name: 'control-point-weights', type: t.numbers },\n    { name: 'segment-distances', type: t.bidirectionalSizes },\n    { name: 'segment-weights', type: t.numbers },\n\n    // these are just for the core\n    { name: 'selection-box-color', type: t.color },\n    { name: 'selection-box-opacity', type: t.zeroOneNumber },\n    { name: 'selection-box-border-color', type: t.color },\n    { name: 'selection-box-border-width', type: t.size },\n    { name: 'active-bg-color', type: t.color },\n    { name: 'active-bg-opacity', type: t.zeroOneNumber },\n    { name: 'active-bg-size', type: t.size },\n    { name: 'outside-texture-bg-color', type: t.color },\n    { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber }\n  ];\n\n  // define aliases\n  var aliases = styfn.aliases = [\n    { name: 'content', pointsTo: 'label' },\n    { name: 'control-point-distance', pointsTo: 'control-point-distances' },\n    { name: 'control-point-weight', pointsTo: 'control-point-weights' }\n  ];\n\n  // pie backgrounds for nodes\n  styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use)\n  props.push({ name: 'pie-size', type: t.bgSize });\n  for( var i = 1; i <= styfn.pieBackgroundN; i++ ){\n    props.push({ name: 'pie-'+i+'-background-color', type: t.color });\n    props.push({ name: 'pie-'+i+'-background-size', type: t.percent });\n    props.push({ name: 'pie-'+i+'-background-opacity', type: t.zeroOneNumber });\n  }\n\n  // edge arrows\n  var arrowPrefixes = styfn.arrowPrefixes = ['source', 'mid-source', 'target', 'mid-target'];\n  [\n    { name: 'arrow-shape', type: t.arrowShape },\n    { name: 'arrow-color', type: t.color },\n    { name: 'arrow-fill', type: t.arrowFill }\n  ].forEach(function( prop ){\n    arrowPrefixes.forEach(function( prefix ){\n      var name = prefix + '-' + prop.name;\n      var type = prop.type;\n\n      props.push({ name: name, type: type });\n    });\n  }, {});\n\n  // list of property names\n  styfn.propertyNames = props.map(function(p){ return p.name; });\n\n  // allow access of properties by name ( e.g. style.properties.height )\n  for( var i = 0; i < props.length; i++ ){\n    var prop = props[i];\n\n    props[ prop.name ] = prop; // allow lookup by name\n  }\n\n  // map aliases\n  for( var i = 0; i < aliases.length; i++ ){\n    var alias = aliases[i];\n    var pointsToProp = props[ alias.pointsTo ];\n    var aliasProp = {\n      name: alias.name,\n      alias: true,\n      pointsTo: pointsToProp\n    };\n\n    // add alias prop for parsing\n    props.push( aliasProp );\n\n    props[ alias.name ] = aliasProp; // allow lookup by name\n  }\n})();\n\n// adds the default stylesheet to the current style\nstyfn.addDefaultStylesheet = function(){\n  // fill the style with the default stylesheet\n  this\n    .selector('node, edge') // common properties\n      .css( util.extend( {\n        'events': 'yes',\n        'text-events': 'no',\n        'text-valign': 'top',\n        'text-halign': 'center',\n        'color': '#000',\n        'text-outline-color': '#000',\n        'text-outline-width': 0,\n        'text-outline-opacity': 1,\n        'text-opacity': 1,\n        'text-decoration': 'none',\n        'text-transform': 'none',\n        'text-wrap': 'none',\n        'text-max-width': 9999,\n        'text-background-color': '#000',\n        'text-background-opacity': 0,\n        'text-border-opacity': 0,\n        'text-border-width': 0,\n        'text-border-style': 'solid',\n        'text-border-color':'#000',\n        'text-background-shape':'rectangle',\n        'font-family': 'Helvetica Neue, Helvetica, sans-serif',\n        'font-style': 'normal',\n        // 'font-variant': fontVariant,\n        'font-weight': 'normal',\n        'font-size': 16,\n        'min-zoomed-font-size': 0,\n        'edge-text-rotation': 'none',\n        'visibility': 'visible',\n        'display': 'element',\n        'opacity': 1,\n        'z-index': 0,\n        'label': '',\n        'overlay-opacity': 0,\n        'overlay-color': '#000',\n        'overlay-padding': 10,\n        'shadow-opacity': 0,\n        'shadow-color': '#000',\n        'shadow-blur': 10,\n        'shadow-offset-x': 0,\n        'shadow-offset-y': 0,\n        'text-shadow-opacity': 0,\n        'text-shadow-color': '#000',\n        'text-shadow-blur': 5,\n        'text-shadow-offset-x': 0,\n        'text-shadow-offset-y': 0,\n        'transition-property': 'none',\n        'transition-duration': 0,\n        'transition-delay': 0,\n        'transition-timing-function': 'linear',\n\n        // node props\n        'background-blacken': 0,\n        'background-color': '#888',\n        'background-opacity': 1,\n        'background-image': 'none',\n        'background-image-opacity': 1,\n        'background-position-x': '50%',\n        'background-position-y': '50%',\n        'background-repeat': 'no-repeat',\n        'background-fit': 'none',\n        'background-clip': 'node',\n        'background-width': 'auto',\n        'background-height': 'auto',\n        'border-color': '#000',\n        'border-opacity': 1,\n        'border-width': 0,\n        'border-style': 'solid',\n        'height': 30,\n        'width': 30,\n        'shape': 'ellipse',\n        'shape-polygon-points': '-1, -1,   1, -1,   1, 1,   -1, 1',\n\n        // compound props\n        'padding-top': 0,\n        'padding-bottom': 0,\n        'padding-left': 0,\n        'padding-right': 0,\n        'position': 'origin',\n        'compound-sizing-wrt-labels': 'include'\n      }, {\n        // node pie bg\n        'pie-size': '100%'\n      }, [\n        { name: 'pie-{{i}}-background-color', value: 'black' },\n        { name: 'pie-{{i}}-background-size', value: '0%' },\n        { name: 'pie-{{i}}-background-opacity', value: 1 }\n      ].reduce(function( css, prop ){\n        for( var i = 1; i <= styfn.pieBackgroundN; i++ ){\n          var name = prop.name.replace('{{i}}', i);\n          var val = prop.value;\n\n          css[ name ] = val;\n        }\n\n        return css;\n      }, {}), {\n        // edge props\n        'line-style': 'solid',\n        'line-color': '#ddd',\n        'control-point-step-size': 40,\n        'control-point-weights': 0.5,\n        'segment-weights': 0.5,\n        'segment-distances': 20,\n        'curve-style': 'bezier',\n        'haystack-radius': 0.8\n      }, [\n        { name: 'arrow-shape', value: 'none' },\n        { name: 'arrow-color', value: '#ddd' },\n        { name: 'arrow-fill', value: 'filled' }\n      ].reduce(function( css, prop ){\n        styfn.arrowPrefixes.forEach(function( prefix ){\n          var name = prefix + '-' + prop.name;\n          var val = prop.value;\n\n          css[ name ] = val;\n        });\n\n        return css;\n      }, {}) ) )\n    .selector('$node > node') // compound (parent) node properties\n      .css({\n        'width': 'auto',\n        'height': 'auto',\n        'shape': 'rectangle',\n        'padding-top': 10,\n        'padding-right': 10,\n        'padding-left': 10,\n        'padding-bottom': 10\n      })\n    .selector('edge') // just edge properties\n      .css({\n        'width': 1\n      })\n    .selector(':active')\n      .css({\n        'overlay-color': 'black',\n        'overlay-padding': 10,\n        'overlay-opacity': 0.25\n      })\n    .selector('core') // just core properties\n      .css({\n        'selection-box-color': '#ddd',\n        'selection-box-opacity': 0.65,\n        'selection-box-border-color': '#aaa',\n        'selection-box-border-width': 1,\n        'active-bg-color': 'black',\n        'active-bg-opacity': 0.15,\n        'active-bg-size': 30,\n        'outside-texture-bg-color': '#000',\n        'outside-texture-bg-opacity': 0.125\n      })\n  ;\n\n  this.defaultLength = this.length;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\nvar Selector = require('../selector');\n\nvar styfn = {};\n\nstyfn.applyFromString = function( string ){\n  var self = this;\n  var style = this;\n  var remaining = '' + string;\n  var selAndBlockStr;\n  var blockRem;\n  var propAndValStr;\n\n  // remove comments from the style string\n  remaining = remaining.replace(/[/][*](\\s|.)+?[*][/]/g, '');\n\n  function removeSelAndBlockFromRemaining(){\n    // remove the parsed selector and block from the remaining text to parse\n    if( remaining.length > selAndBlockStr.length ){\n      remaining = remaining.substr( selAndBlockStr.length );\n    } else {\n      remaining = '';\n    }\n  }\n\n  function removePropAndValFromRem(){\n    // remove the parsed property and value from the remaining block text to parse\n    if( blockRem.length > propAndValStr.length ){\n      blockRem = blockRem.substr( propAndValStr.length );\n    } else {\n      blockRem = '';\n    }\n  }\n\n  while(true){\n    var nothingLeftToParse = remaining.match(/^\\s*$/);\n    if( nothingLeftToParse ){ break; }\n\n    var selAndBlock = remaining.match(/^\\s*((?:.|\\s)+?)\\s*\\{((?:.|\\s)+?)\\}/);\n\n    if( !selAndBlock ){\n      util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);\n      break;\n    }\n\n    selAndBlockStr = selAndBlock[0];\n\n    // parse the selector\n    var selectorStr = selAndBlock[1];\n    if( selectorStr !== 'core' ){\n      var selector = new Selector( selectorStr );\n      if( selector._private.invalid ){\n        util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr);\n\n        // skip this selector and block\n        removeSelAndBlockFromRemaining();\n        continue;\n      }\n    }\n\n    // parse the block of properties and values\n    var blockStr = selAndBlock[2];\n    var invalidBlock = false;\n    blockRem = blockStr;\n    var props = [];\n\n    while(true){\n      var nothingLeftToParse = blockRem.match(/^\\s*$/);\n      if( nothingLeftToParse ){ break; }\n\n      var propAndVal = blockRem.match(/^\\s*(.+?)\\s*:\\s*(.+?)\\s*;/);\n\n      if( !propAndVal ){\n        util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);\n        invalidBlock = true;\n        break;\n      }\n\n      propAndValStr = propAndVal[0];\n      var propStr = propAndVal[1];\n      var valStr = propAndVal[2];\n\n      var prop = self.properties[ propStr ];\n      if( !prop ){\n        util.error('Skipping property: Invalid property name in: ' + propAndValStr);\n\n        // skip this property in the block\n        removePropAndValFromRem();\n        continue;\n      }\n\n      var parsedProp = style.parse( propStr, valStr );\n\n      if( !parsedProp ){\n        util.error('Skipping property: Invalid property definition in: ' + propAndValStr);\n\n        // skip this property in the block\n        removePropAndValFromRem();\n        continue;\n      }\n\n      props.push({\n        name: propStr,\n        val: valStr\n      });\n      removePropAndValFromRem();\n    }\n\n    if( invalidBlock ){\n      removeSelAndBlockFromRemaining();\n      break;\n    }\n\n    // put the parsed block in the style\n    style.selector( selectorStr );\n    for( var i = 0; i < props.length; i++ ){\n      var prop = props[i];\n      style.css( prop.name, prop.val );\n    }\n\n    removeSelAndBlockFromRemaining();\n  }\n\n  return style;\n};\n\nstyfn.fromString = function( string ){\n  var style = this;\n\n  style.resetToDefault();\n  style.applyFromString( string );\n\n  return style;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar is = require('./is');\nvar util = require('./util');\nvar Style = require('./style');\n\n// a dummy stylesheet object that doesn't need a reference to the core\n// (useful for init)\nvar Stylesheet = function(){\n  if( !(this instanceof Stylesheet) ){\n    return new Stylesheet();\n  }\n\n  this.length = 0;\n};\n\nvar sheetfn = Stylesheet.prototype;\n\nsheetfn.instanceString = function(){\n  return 'stylesheet';\n};\n\n// just store the selector to be parsed later\nsheetfn.selector = function( selector ){\n  var i = this.length++;\n\n  this[i] = {\n    selector: selector,\n    properties: []\n  };\n\n  return this; // chaining\n};\n\n// just store the property to be parsed later\nsheetfn.css = function( name, value ){\n  var i = this.length - 1;\n\n  if( is.string(name) ){\n    this[i].properties.push({\n      name: name,\n      value: value\n    });\n  } else if( is.plainObject(name) ){\n    var map = name;\n\n    for( var j = 0; j < Style.properties.length; j++ ){\n      var prop = Style.properties[j];\n      var mapVal = map[ prop.name ];\n\n      if( mapVal === undefined ){ // also try camel case name\n        mapVal = map[ util.dash2camel(prop.name) ];\n      }\n\n      if( mapVal !== undefined ){\n        var name = prop.name;\n        var value = mapVal;\n\n        this[i].properties.push({\n          name: name,\n          value: value\n        });\n      }\n    }\n  }\n\n  return this; // chaining\n};\n\nsheetfn.style = sheetfn.css;\n\n// generate a real style object from the dummy stylesheet\nsheetfn.generateStyle = function( cy ){\n  var style = new Style(cy);\n\n  for( var i = 0; i < this.length; i++ ){\n    var context = this[i];\n    var selector = context.selector;\n    var props = context.properties;\n\n    style.selector(selector); // apply selector\n\n    for( var j = 0; j < props.length; j++ ){\n      var prop = props[j];\n\n      style.css( prop.name, prop.value ); // apply property\n    }\n  }\n\n  return style;\n};\n\nmodule.exports = Stylesheet;\n","// cross-env thread/worker\n// NB : uses (heavyweight) processes on nodejs so best not to create too many threads\n\n'use strict';\n\nvar window = require('./window');\nvar util = require('./util');\nvar Promise = require('./promise');\nvar Event = require('./event');\nvar define = require('./define');\nvar is = require('./is');\n\nvar Thread = function( opts ){\n  if( !(this instanceof Thread) ){\n    return new Thread( opts );\n  }\n\n  var _p = this._private = {\n    requires: [],\n    files: [],\n    queue: null,\n    pass: [],\n    disabled: false\n  };\n\n  if( is.plainObject(opts) ){\n    if( opts.disabled != null ){\n      _p.disabled = !!opts.disabled;\n    }\n  }\n\n};\n\nvar thdfn = Thread.prototype; // short alias\n\nvar stringifyFieldVal = function( val ){\n  var valStr = is.fn( val ) ? val.toString() : 'JSON.parse(\"' + JSON.stringify(val) + '\")';\n\n  return valStr;\n};\n\n// allows for requires with prototypes and subobjs etc\nvar fnAsRequire = function( fn ){\n  var req;\n  var fnName;\n\n  if( is.object(fn) && fn.fn ){ // manual fn\n    req = fnAs( fn.fn, fn.name );\n    fnName = fn.name;\n    fn = fn.fn;\n  } else if( is.fn(fn) ){ // auto fn\n    req = fn.toString();\n    fnName = fn.name;\n  } else if( is.string(fn) ){ // stringified fn\n    req = fn;\n  } else if( is.object(fn) ){ // plain object\n    if( fn.proto ){\n      req = '';\n    } else {\n      req = fn.name + ' = {};';\n    }\n\n    fnName = fn.name;\n    fn = fn.obj;\n  }\n\n  req += '\\n';\n\n  var protoreq = function( val, subname ){\n    if( val.prototype ){\n      var protoNonempty = false;\n      for( var prop in val.prototype ){ protoNonempty = true; break; } // jshint ignore:line\n\n      if( protoNonempty ){\n        req += fnAsRequire( {\n          name: subname,\n          obj: val,\n          proto: true\n        }, val );\n      }\n    }\n  };\n\n  // pull in prototype\n  if( fn.prototype && fnName != null ){\n\n    for( var name in fn.prototype ){\n      var protoStr = '';\n\n      var val = fn.prototype[ name ];\n      var valStr = stringifyFieldVal( val );\n      var subname = fnName + '.prototype.' + name;\n\n      protoStr += subname + ' = ' + valStr + ';\\n';\n\n      if( protoStr ){\n        req += protoStr;\n      }\n\n      protoreq( val, subname ); // subobject with prototype\n    }\n\n  }\n\n  // pull in properties for obj/fns\n  if( !is.string(fn) ){ for( var name in fn ){\n    var propsStr = '';\n\n    if( fn.hasOwnProperty(name) ){\n      var val = fn[ name ];\n      var valStr = stringifyFieldVal( val );\n      var subname = fnName + '[\"' + name + '\"]';\n\n      propsStr += subname + ' = ' + valStr + ';\\n';\n    }\n\n    if( propsStr ){\n      req += propsStr;\n    }\n\n    protoreq( val, subname ); // subobject with prototype\n  } }\n\n  return req;\n};\n\nvar isPathStr = function( str ){\n  return is.string(str) && str.match(/\\.js$/);\n};\n\nutil.extend(thdfn, {\n\n  instanceString: function(){ return 'thread'; },\n\n  require: function( fn, as ){\n    var requires = this._private.requires;\n\n    if( isPathStr(fn) ){\n      this._private.files.push( fn );\n\n      return this;\n    }\n\n    if( as ){\n      if( is.fn(fn) ){\n        fn = { name: as, fn: fn };\n      } else {\n        fn = { name: as, obj: fn };\n      }\n    } else {\n      if( is.fn(fn) ){\n        if( !fn.name ){\n          throw 'The function name could not be automatically determined.  Use thread.require( someFunction, \"someFunction\" )';\n        }\n\n        fn = { name: fn.name, fn: fn };\n      }\n    }\n\n    requires.push( fn );\n\n    return this; // chaining\n  },\n\n  pass: function( data ){\n    this._private.pass.push( data );\n\n    return this; // chaining\n  },\n\n  run: function( fn, pass ){ // fn used like main()\n    var self = this;\n    var _p = this._private;\n    pass = pass || _p.pass.shift();\n\n    if( _p.stopped ){\n      throw 'Attempted to run a stopped thread!  Start a new thread or do not stop the existing thread and reuse it.';\n    }\n\n    if( _p.running ){\n      return ( _p.queue = _p.queue.then(function(){ // inductive step\n        return self.run( fn, pass );\n      }) );\n    }\n\n    var useWW = window != null && !_p.disabled;\n    var useNode = !window && typeof module !== 'undefined' && !_p.disabled;\n\n    self.trigger('run');\n\n    var runP = new Promise(function( resolve, reject ){\n\n      _p.running = true;\n\n      var threadTechAlreadyExists = _p.ran;\n\n      var fnImplStr = is.string( fn ) ? fn : fn.toString();\n\n      // worker code to exec\n      var fnStr = '\\n' + ( _p.requires.map(function( r ){\n        return fnAsRequire( r );\n      }) ).concat( _p.files.map(function( f ){\n        if( useWW ){\n          var wwifyFile = function( file ){\n            if( file.match(/^\\.\\//) || file.match(/^\\.\\./) ){\n              return window.location.origin + window.location.pathname + file;\n            } else if( file.match(/^\\//) ){\n              return window.location.origin + '/' + file;\n            }\n            return file;\n          };\n\n          return 'importScripts(\"' + wwifyFile(f) + '\");';\n        } else if( useNode ) {\n          return 'eval( require(\"fs\").readFileSync(\"' + f + '\", { encoding: \"utf8\" }) );';\n        } else {\n          throw 'External file `' + f + '` can not be required without any threading technology.';\n        }\n      }) ).concat([\n        '( function(){',\n          'var ret = (' + fnImplStr + ')(' + JSON.stringify(pass) + ');',\n          'if( ret !== undefined ){ resolve(ret); }', // assume if ran fn returns defined value (incl. null), that we want to resolve to it\n        '} )()\\n'\n      ]).join('\\n');\n\n      // because we've now consumed the requires, empty the list so we don't dupe on next run()\n      _p.requires = [];\n      _p.files = [];\n\n      if( useWW ){\n        var fnBlob, fnUrl;\n\n        // add normalised thread api functions\n        if( !threadTechAlreadyExists ){\n          var fnPre = fnStr + '';\n\n          fnStr = [\n            'function _ref_(o){ return eval(o); };',\n            'function broadcast(m){ return message(m); };', // alias\n            'function message(m){ postMessage(m); };',\n            'function listen(fn){',\n            '  self.addEventListener(\"message\", function(m){ ',\n            '    if( typeof m === \"object\" && (m.data.$$eval || m.data === \"$$start\") ){',\n            '    } else { ',\n            '      fn( m.data );',\n            '    }',\n            '  });',\n            '};',\n            'self.addEventListener(\"message\", function(m){  if( m.data.$$eval ){ eval( m.data.$$eval ); }  });',\n            'function resolve(v){ postMessage({ $$resolve: v }); };',\n            'function reject(v){ postMessage({ $$reject: v }); };'\n          ].join('\\n');\n\n          fnStr += fnPre;\n\n          fnBlob = new Blob([ fnStr ], {\n            type: 'application/javascript'\n          });\n          fnUrl = window.URL.createObjectURL( fnBlob );\n        }\n        // create webworker and let it exec the serialised code\n        var ww = _p.webworker = _p.webworker || new Worker( fnUrl );\n\n        if( threadTechAlreadyExists ){ // then just exec new run() code\n          ww.postMessage({\n            $$eval: fnStr\n          });\n        }\n\n        // worker messages => events\n        var cb;\n        ww.addEventListener('message', cb = function( m ){\n          var isObject = is.object(m) && is.object( m.data );\n\n          if( isObject && ('$$resolve' in m.data) ){\n            ww.removeEventListener('message', cb); // done listening b/c resolve()\n\n            resolve( m.data.$$resolve );\n          } else if( isObject && ('$$reject' in m.data) ){\n            ww.removeEventListener('message', cb); // done listening b/c reject()\n\n            reject( m.data.$$reject );\n          } else {\n            self.trigger( new Event(m, { type: 'message', message: m.data }) );\n          }\n        }, false);\n\n        if( !threadTechAlreadyExists ){\n          ww.postMessage('$$start'); // start up the worker\n        }\n\n      } else if( useNode ){\n        // create a new process\n\n        if( !_p.child ){\n          _p.child = ( require('child_process').fork( require('path').join(__dirname, 'thread-node-fork') ) );\n        }\n\n        var child = _p.child;\n\n        // child process messages => events\n        var cb;\n        child.on('message', cb = function( m ){\n          if( is.object(m) && ('$$resolve' in m) ){\n            child.removeListener('message', cb); // done listening b/c resolve()\n\n            resolve( m.$$resolve );\n          } else if( is.object(m) && ('$$reject' in m) ){\n            child.removeListener('message', cb); // done listening b/c reject()\n\n            reject( m.$$reject );\n          } else {\n            self.trigger( new Event({}, { type: 'message', message: m }) );\n          }\n        });\n\n        // ask the child process to eval the worker code\n        child.send({\n          $$eval: fnStr\n        });\n\n      } else { // use a fallback mechanism using a timeout\n\n        var promiseResolve = resolve;\n        var promiseReject = reject;\n\n        var timer = _p.timer = _p.timer || {\n\n          listeners: [],\n\n          exec: function(){\n            // as a string so it can't be mangled by minifiers and processors\n            fnStr = [\n              'function _ref_(o){ return eval(o); };',\n              'function broadcast(m){ return message(m); };',\n              'function message(m){ self.trigger( new Event({}, { type: \"message\", message: m }) ); };',\n              'function listen(fn){ timer.listeners.push( fn ); };',\n              'function resolve(v){ promiseResolve(v); };',\n              'function reject(v){ promiseReject(v); };'\n            ].join('\\n') + fnStr;\n\n            // the .run() code\n            eval( fnStr ); // jshint ignore:line\n          },\n\n          message: function( m ){\n            var ls = timer.listeners;\n\n            for( var i = 0; i < ls.length; i++ ){\n              var fn = ls[i];\n\n              fn( m );\n            }\n          }\n\n        };\n\n        timer.exec();\n      }\n\n    }).then(function( v ){\n      _p.running = false;\n      _p.ran = true;\n\n      self.trigger('ran');\n\n      return v;\n    });\n\n    if( _p.queue == null ){\n      _p.queue = runP; // i.e. first step of inductive promise chain (for queue)\n    }\n\n    return runP;\n  },\n\n  // send the thread a message\n  message: function( m ){\n    var _p = this._private;\n\n    if( _p.webworker ){\n      _p.webworker.postMessage( m );\n    }\n\n    if( _p.child ){\n      _p.child.send( m );\n    }\n\n    if( _p.timer ){\n      _p.timer.message( m );\n    }\n\n    return this; // chaining\n  },\n\n  stop: function(){\n    var _p = this._private;\n\n    if( _p.webworker ){\n      _p.webworker.terminate();\n    }\n\n    if( _p.child ){\n      _p.child.kill();\n    }\n\n    if( _p.timer ){\n      // nothing we can do if we've run a timeout\n    }\n\n    _p.stopped = true;\n\n    return this.trigger('stop'); // chaining\n  },\n\n  stopped: function(){\n    return this._private.stopped;\n  }\n\n});\n\n// turns a stringified function into a (re)named function\nvar fnAs = function( fn, name ){\n  var fnStr = fn.toString();\n  fnStr = fnStr.replace(/function\\s*?\\S*?\\s*?\\(/, 'function ' + name + '(');\n\n  return fnStr;\n};\n\nvar defineFnal = function( opts ){\n  opts = opts || {};\n\n  return function fnalImpl( fn, arg1 ){\n    var fnStr = fnAs( fn, '_$_$_' + opts.name );\n\n    this.require( fnStr );\n\n    return this.run( [\n      'function( data ){',\n      '  var origResolve = resolve;',\n      '  var res = [];',\n      '  ',\n      '  resolve = function( val ){',\n      '    res.push( val );',\n      '  };',\n      '  ',\n      '  var ret = data.' + opts.name + '( _$_$_' + opts.name + ( arguments.length > 1 ? ', ' + JSON.stringify(arg1) : '' ) + ' );',\n      '  ',\n      '  resolve = origResolve;',\n      '  resolve( res.length > 0 ? res : ret );',\n      '}'\n    ].join('\\n') );\n  };\n};\n\nutil.extend(thdfn, {\n  reduce: defineFnal({ name: 'reduce' }),\n\n  reduceRight: defineFnal({ name: 'reduceRight' }),\n\n  map: defineFnal({ name: 'map' })\n});\n\n// aliases\nvar fn = thdfn;\nfn.promise = fn.run;\nfn.terminate = fn.halt = fn.stop;\nfn.include = fn.require;\n\n// pull in event apis\nutil.extend(thdfn, {\n  on: define.on(),\n  one: define.on({ unbindSelfOnTrigger: true }),\n  off: define.off(),\n  trigger: define.trigger()\n});\n\ndefine.eventAliasesOn( thdfn );\n\nmodule.exports = Thread;\n","'use strict';\n\nvar is = require('../is');\n\nmodule.exports = {\n  // get [r, g, b] from #abc or #aabbcc\n  hex2tuple: function( hex ){\n    if( !(hex.length === 4 || hex.length === 7) || hex[0] !== \"#\" ){ return; }\n\n    var shortHex = hex.length === 4;\n    var r, g, b;\n    var base = 16;\n\n    if( shortHex ){\n      r = parseInt( hex[1] + hex[1], base );\n      g = parseInt( hex[2] + hex[2], base );\n      b = parseInt( hex[3] + hex[3], base );\n    } else {\n      r = parseInt( hex[1] + hex[2], base );\n      g = parseInt( hex[3] + hex[4], base );\n      b = parseInt( hex[5] + hex[6], base );\n    }\n\n    return [r, g, b];\n  },\n\n  // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0)\n  hsl2tuple: function( hsl ){\n    var ret;\n    var h, s, l, a, r, g, b;\n    function hue2rgb(p, q, t){\n      if(t < 0) t += 1;\n      if(t > 1) t -= 1;\n      if(t < 1/6) return p + (q - p) * 6 * t;\n      if(t < 1/2) return q;\n      if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n      return p;\n    }\n\n    var m = new RegExp(\"^\" + this.regex.hsla + \"$\").exec(hsl);\n    if( m ){\n\n      // get hue\n      h = parseInt( m[1] );\n      if( h < 0 ){\n        h = ( 360 - (-1*h % 360) ) % 360;\n      } else if( h > 360 ){\n        h = h % 360;\n      }\n      h /= 360; // normalise on [0, 1]\n\n      s = parseFloat( m[2] );\n      if( s < 0 || s > 100 ){ return; } // saturation is [0, 100]\n      s = s/100; // normalise on [0, 1]\n\n      l = parseFloat( m[3] );\n      if( l < 0 || l > 100 ){ return; } // lightness is [0, 100]\n      l = l/100; // normalise on [0, 1]\n\n      a = m[4];\n      if( a !== undefined ){\n        a = parseFloat( a );\n\n        if( a < 0 || a > 1 ){ return; } // alpha is [0, 1]\n      }\n\n      // now, convert to rgb\n      // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript\n      if( s === 0 ){\n        r = g = b = Math.round(l * 255); // achromatic\n      } else {\n        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n        var p = 2 * l - q;\n        r = Math.round( 255 * hue2rgb(p, q, h + 1/3) );\n        g = Math.round( 255 * hue2rgb(p, q, h) );\n        b = Math.round( 255 * hue2rgb(p, q, h - 1/3) );\n      }\n\n      ret = [r, g, b, a];\n    }\n\n    return ret;\n  },\n\n  // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0)\n  rgb2tuple: function( rgb ){\n    var ret;\n\n    var m = new RegExp(\"^\" + this.regex.rgba + \"$\").exec(rgb);\n    if( m ){\n      ret = [];\n\n      var isPct = [];\n      for( var i = 1; i <= 3; i++ ){\n        var channel = m[i];\n\n        if( channel[ channel.length - 1 ] === \"%\" ){\n          isPct[i] = true;\n        }\n        channel = parseFloat( channel );\n\n        if( isPct[i] ){\n          channel = channel/100 * 255; // normalise to [0, 255]\n        }\n\n        if( channel < 0 || channel > 255 ){ return; } // invalid channel value\n\n        ret.push( Math.floor(channel) );\n      }\n\n      var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3];\n      var allArePct = isPct[1] && isPct[2] && isPct[3];\n      if( atLeastOneIsPct && !allArePct ){ return; } // must all be percent values if one is\n\n      var alpha = m[4];\n      if( alpha !== undefined ){\n        alpha = parseFloat( alpha );\n\n        if( alpha < 0 || alpha > 1 ){ return; } // invalid alpha value\n\n        ret.push( alpha );\n      }\n    }\n\n    return ret;\n  },\n\n  colorname2tuple: function( color ){\n    return this.colors[ color.toLowerCase() ];\n  },\n\n  color2tuple: function( color ){\n    return ( is.array(color) ? color : null )\n      || this.colorname2tuple(color)\n      || this.hex2tuple(color)\n      || this.rgb2tuple(color)\n      || this.hsl2tuple(color);\n  },\n\n  colors: {\n    // special colour names\n    transparent: [0, 0, 0, 0], // NB alpha === 0\n\n    // regular colours\n    aliceblue: [240, 248, 255],\n    antiquewhite: [250, 235, 215],\n    aqua: [0, 255, 255],\n    aquamarine: [127, 255, 212],\n    azure: [240, 255, 255],\n    beige: [245, 245, 220],\n    bisque: [255, 228, 196],\n    black: [0, 0, 0],\n    blanchedalmond: [255, 235, 205],\n    blue: [0, 0, 255],\n    blueviolet: [138, 43, 226],\n    brown: [165, 42, 42],\n    burlywood: [222, 184, 135],\n    cadetblue: [95, 158, 160],\n    chartreuse: [127, 255, 0],\n    chocolate: [210, 105, 30],\n    coral: [255, 127, 80],\n    cornflowerblue: [100, 149, 237],\n    cornsilk: [255, 248, 220],\n    crimson: [220, 20, 60],\n    cyan: [0, 255, 255],\n    darkblue: [0, 0, 139],\n    darkcyan: [0, 139, 139],\n    darkgoldenrod: [184, 134, 11],\n    darkgray: [169, 169, 169],\n    darkgreen: [0, 100, 0],\n    darkgrey: [169, 169, 169],\n    darkkhaki: [189, 183, 107],\n    darkmagenta: [139, 0, 139],\n    darkolivegreen: [85, 107, 47],\n    darkorange: [255, 140, 0],\n    darkorchid: [153, 50, 204],\n    darkred: [139, 0, 0],\n    darksalmon: [233, 150, 122],\n    darkseagreen: [143, 188, 143],\n    darkslateblue: [72, 61, 139],\n    darkslategray: [47, 79, 79],\n    darkslategrey: [47, 79, 79],\n    darkturquoise: [0, 206, 209],\n    darkviolet: [148, 0, 211],\n    deeppink: [255, 20, 147],\n    deepskyblue: [0, 191, 255],\n    dimgray: [105, 105, 105],\n    dimgrey: [105, 105, 105],\n    dodgerblue: [30, 144, 255],\n    firebrick: [178, 34, 34],\n    floralwhite: [255, 250, 240],\n    forestgreen: [34, 139, 34],\n    fuchsia: [255, 0, 255],\n    gainsboro: [220, 220, 220],\n    ghostwhite: [248, 248, 255],\n    gold: [255, 215, 0],\n    goldenrod: [218, 165, 32],\n    gray: [128, 128, 128],\n    grey: [128, 128, 128],\n    green: [0, 128, 0],\n    greenyellow: [173, 255, 47],\n    honeydew: [240, 255, 240],\n    hotpink: [255, 105, 180],\n    indianred: [205, 92, 92],\n    indigo: [75, 0, 130],\n    ivory: [255, 255, 240],\n    khaki: [240, 230, 140],\n    lavender: [230, 230, 250],\n    lavenderblush: [255, 240, 245],\n    lawngreen: [124, 252, 0],\n    lemonchiffon: [255, 250, 205],\n    lightblue: [173, 216, 230],\n    lightcoral: [240, 128, 128],\n    lightcyan: [224, 255, 255],\n    lightgoldenrodyellow: [250, 250, 210],\n    lightgray: [211, 211, 211],\n    lightgreen: [144, 238, 144],\n    lightgrey: [211, 211, 211],\n    lightpink: [255, 182, 193],\n    lightsalmon: [255, 160, 122],\n    lightseagreen: [32, 178, 170],\n    lightskyblue: [135, 206, 250],\n    lightslategray: [119, 136, 153],\n    lightslategrey: [119, 136, 153],\n    lightsteelblue: [176, 196, 222],\n    lightyellow: [255, 255, 224],\n    lime: [0, 255, 0],\n    limegreen: [50, 205, 50],\n    linen: [250, 240, 230],\n    magenta: [255, 0, 255],\n    maroon: [128, 0, 0],\n    mediumaquamarine: [102, 205, 170],\n    mediumblue: [0, 0, 205],\n    mediumorchid: [186, 85, 211],\n    mediumpurple: [147, 112, 219],\n    mediumseagreen: [60, 179, 113],\n    mediumslateblue: [123, 104, 238],\n    mediumspringgreen: [0, 250, 154],\n    mediumturquoise: [72, 209, 204],\n    mediumvioletred: [199, 21, 133],\n    midnightblue: [25, 25, 112],\n    mintcream: [245, 255, 250],\n    mistyrose: [255, 228, 225],\n    moccasin: [255, 228, 181],\n    navajowhite: [255, 222, 173],\n    navy: [0, 0, 128],\n    oldlace: [253, 245, 230],\n    olive: [128, 128, 0],\n    olivedrab: [107, 142, 35],\n    orange: [255, 165, 0],\n    orangered: [255, 69, 0],\n    orchid: [218, 112, 214],\n    palegoldenrod: [238, 232, 170],\n    palegreen: [152, 251, 152],\n    paleturquoise: [175, 238, 238],\n    palevioletred: [219, 112, 147],\n    papayawhip: [255, 239, 213],\n    peachpuff: [255, 218, 185],\n    peru: [205, 133, 63],\n    pink: [255, 192, 203],\n    plum: [221, 160, 221],\n    powderblue: [176, 224, 230],\n    purple: [128, 0, 128],\n    red: [255, 0, 0],\n    rosybrown: [188, 143, 143],\n    royalblue: [65, 105, 225],\n    saddlebrown: [139, 69, 19],\n    salmon: [250, 128, 114],\n    sandybrown: [244, 164, 96],\n    seagreen: [46, 139, 87],\n    seashell: [255, 245, 238],\n    sienna: [160, 82, 45],\n    silver: [192, 192, 192],\n    skyblue: [135, 206, 235],\n    slateblue: [106, 90, 205],\n    slategray: [112, 128, 144],\n    slategrey: [112, 128, 144],\n    snow: [255, 250, 250],\n    springgreen: [0, 255, 127],\n    steelblue: [70, 130, 180],\n    tan: [210, 180, 140],\n    teal: [0, 128, 128],\n    thistle: [216, 191, 216],\n    tomato: [255, 99, 71],\n    turquoise: [64, 224, 208],\n    violet: [238, 130, 238],\n    wheat: [245, 222, 179],\n    white: [255, 255, 255],\n    whitesmoke: [245, 245, 245],\n    yellow: [255, 255, 0],\n    yellowgreen: [154, 205, 50]\n  }\n};\n","'use strict';\n\nvar is = require('../is');\nvar math = require('../math');\n\nvar util = {\n\n  falsify: function(){ return false; },\n\n  zeroify: function(){ return 0; },\n\n  noop: function(){},\n\n  /* jshint ignore:start */\n  error: function( msg ){\n    if( console.error ){\n      console.error.apply( console, arguments );\n\n      if( console.trace ){ console.trace(); }\n    } else {\n      console.log.apply( console, arguments );\n\n      if( console.trace ){ console.trace(); }\n    }\n  },\n  /* jshint ignore:end */\n\n  clone: function( obj ){\n    return this.extend( {}, obj );\n  },\n\n  // gets a shallow copy of the argument\n  copy: function( obj ){\n    if( obj == null ){\n      return obj;\n    } if( is.array(obj) ){\n      return obj.slice();\n    } else if( is.plainObject(obj) ){\n      return this.clone( obj );\n    } else {\n      return obj;\n    }\n  }\n\n};\n\nutil.makeBoundingBox = math.makeBoundingBox.bind( math );\n\nutil._staticEmptyObject = {};\n\nutil.staticEmptyObject = function(){\n  return util._staticEmptyObject;\n};\n\nutil.extend = Object.assign != null ? Object.assign : function( tgt ){\n  var args = arguments;\n\n  for( var i = 1; i < args.length; i++ ){\n    var obj = args[i];\n\n    for( var k in obj ){\n      tgt[k] = obj[k];\n    }\n  }\n\n  return tgt;\n};\n\n[\n  require('./colors'),\n  require('./maps'),\n  { memoize: require('./memoize') },\n  require('./regex'),\n  require('./strings'),\n  require('./timing')\n].forEach(function( req ){\n  util.extend( util, req );\n});\n\nmodule.exports = util;\n","'use strict';\n\nvar is = require('../is');\n\nmodule.exports = {\n  // has anything been set in the map\n  mapEmpty: function( map ){\n    var empty = true;\n\n    if( map != null ){\n      for(var i in map){ // jshint ignore:line\n        empty = false;\n        break;\n      }\n    }\n\n    return empty;\n  },\n\n  // pushes to the array at the end of a map (map may not be built)\n  pushMap: function( options ){\n    var array = this.getMap(options);\n\n    if( array == null ){ // if empty, put initial array\n      this.setMap( this.extend({}, options, {\n        value: [ options.value ]\n      }) );\n    } else {\n      array.push( options.value );\n    }\n  },\n\n  // sets the value in a map (map may not be built)\n  setMap: function( options ){\n    var obj = options.map;\n    var key;\n    var keys = options.keys;\n    var l = keys.length;\n\n    for(var i = 0; i < l; i++){\n      var key = keys[i];\n\n      if( is.plainObject( key ) ){\n        this.error('Tried to set map with object key');\n      }\n\n      if( i < keys.length - 1 ){\n\n        // extend the map if necessary\n        if( obj[key] == null ){\n          obj[key] = {};\n        }\n\n        obj = obj[key];\n      } else {\n        // set the value\n        obj[key] = options.value;\n      }\n    }\n  },\n\n  // gets the value in a map even if it's not built in places\n  getMap: function( options ){\n    var obj = options.map;\n    var keys = options.keys;\n    var l = keys.length;\n\n    for(var i = 0; i < l; i++){\n      var key = keys[i];\n\n      if( is.plainObject( key ) ){\n        this.error('Tried to get map with object key');\n      }\n\n      obj = obj[key];\n\n      if( obj == null ){\n        return obj;\n      }\n    }\n\n    return obj;\n  },\n\n  // deletes the entry in the map\n  deleteMap: function( options ){\n    var obj = options.map;\n    var keys = options.keys;\n    var l = keys.length;\n    var keepChildren = options.keepChildren;\n\n    for(var i = 0; i < l; i++){\n      var key = keys[i];\n\n      if( is.plainObject( key ) ){\n        this.error('Tried to delete map with object key');\n      }\n\n      var lastKey = i === options.keys.length - 1;\n      if( lastKey ){\n\n        if( keepChildren ){ // then only delete child fields not in keepChildren\n          for( var child in obj ){\n            if( !keepChildren[child] ){\n              obj[child] = undefined;\n            }\n          }\n        } else {\n          obj[key] = undefined;\n        }\n\n      } else {\n        obj = obj[key];\n      }\n    }\n  }\n};\n","'use strict';\n\nmodule.exports = function memoize( fn, keyFn ){\n  var self = this;\n  var cache = {};\n\n  if( !keyFn ){\n    keyFn = function(){\n      if( arguments.length === 1 ){\n        return arguments[0];\n      }\n\n      var args = [];\n\n      for( var i = 0; i < arguments.length; i++ ){\n        args.push( arguments[i] );\n      }\n\n      return args.join('$');\n    };\n  }\n\n  return function memoizedFn(){\n    var args = arguments;\n    var ret;\n    var k = keyFn.apply( self, args );\n\n    if( !(ret = cache[k]) ){\n      ret = cache[k] = fn.apply( self, args );\n    }\n\n    return ret;\n  };\n};\n","'use strict';\n\nvar number = \"(?:[-+]?(?:(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[Ee][+-]?\\\\d+)?))\";\n\nvar rgba = \"rgb[a]?\\\\((\"+ number +\"[%]?)\\\\s*,\\\\s*(\"+ number +\"[%]?)\\\\s*,\\\\s*(\"+ number +\"[%]?)(?:\\\\s*,\\\\s*(\"+ number +\"))?\\\\)\";\nvar rgbaNoBackRefs = \"rgb[a]?\\\\((?:\"+ number +\"[%]?)\\\\s*,\\\\s*(?:\"+ number +\"[%]?)\\\\s*,\\\\s*(?:\"+ number +\"[%]?)(?:\\\\s*,\\\\s*(?:\"+ number +\"))?\\\\)\";\n\nvar hsla = \"hsl[a]?\\\\((\"+ number +\")\\\\s*,\\\\s*(\"+ number +\"[%])\\\\s*,\\\\s*(\"+ number +\"[%])(?:\\\\s*,\\\\s*(\"+ number +\"))?\\\\)\";\nvar hslaNoBackRefs = \"hsl[a]?\\\\((?:\"+ number +\")\\\\s*,\\\\s*(?:\"+ number +\"[%])\\\\s*,\\\\s*(?:\"+ number +\"[%])(?:\\\\s*,\\\\s*(?:\"+ number +\"))?\\\\)\";\n\nvar hex3 = \"\\\\#[0-9a-fA-F]{3}\";\nvar hex6 = \"\\\\#[0-9a-fA-F]{6}\";\n\nmodule.exports = {\n  regex: {\n    number: number,\n    rgba: rgba,\n    rgbaNoBackRefs: rgbaNoBackRefs,\n    hsla: hsla,\n    hslaNoBackRefs: hslaNoBackRefs,\n    hex3: hex3,\n    hex6: hex6\n  }\n};\n","'use strict';\n\nvar memoize = require('./memoize');\nvar is = require('../is');\n\nmodule.exports = {\n\n  camel2dash: memoize( function( str ){\n    return str.replace(/([A-Z])/g, function( v ){\n      return '-' + v.toLowerCase();\n    });\n  } ),\n\n  dash2camel: memoize( function( str ){\n    return str.replace(/(-\\w)/g, function( v ){\n      return v[1].toUpperCase();\n    });\n  } ),\n\n  capitalize: function(str){\n    if( is.emptyString(str) ){\n      return str;\n    }\n\n    return str.charAt(0).toUpperCase() + str.substring(1);\n  }\n\n};\n","'use strict';\n\nvar window = require('../window');\nvar is = require('../is');\nvar performance = window ? window.performance : null;\n\nvar util = {};\n\nvar raf = !window ? null : ( window.requestAnimationFrame || window.mozRequestAnimationFrame ||\n      window.webkitRequestAnimationFrame || window.msRequestAnimationFrame );\n\nraf = raf || function( fn ){\n  if( fn ){\n    setTimeout(function(){\n      fn( pnow() );\n    }, 1000/60);\n  }\n};\n\nutil.requestAnimationFrame = function(fn){\n  raf( fn );\n};\n\nvar pnow = performance && performance.now ? function(){ return performance.now(); } : function(){ return Date.now(); };\n\nutil.performanceNow = pnow;\n\n// ported lodash throttle function\nutil.throttle = function(func, wait, options) {\n  var leading = true,\n      trailing = true;\n\n  if (options === false) {\n    leading = false;\n  } else if (is.plainObject(options)) {\n    leading = 'leading' in options ? options.leading : leading;\n    trailing = 'trailing' in options ? options.trailing : trailing;\n  }\n  options = options || {};\n  options.leading = leading;\n  options.maxWait = wait;\n  options.trailing = trailing;\n\n  return util.debounce(func, wait, options);\n};\n\nutil.now = function(){\n  return Date.now();\n};\n\nutil.debounce = function(func, wait, options) { // ported lodash debounce function\n  var util = this;\n  var args,\n      maxTimeoutId,\n      result,\n      stamp,\n      thisArg,\n      timeoutId,\n      trailingCall,\n      lastCalled = 0,\n      maxWait = false,\n      trailing = true;\n\n  if (!is.fn(func)) {\n    return;\n  }\n  wait = Math.max(0, wait) || 0;\n  if (options === true) {\n    var leading = true;\n    trailing = false;\n  } else if (is.plainObject(options)) {\n    leading = options.leading;\n    maxWait = 'maxWait' in options && (Math.max(wait, options.maxWait) || 0);\n    trailing = 'trailing' in options ? options.trailing : trailing;\n  }\n  var delayed = function() {\n    var remaining = wait - (util.now() - stamp);\n    if (remaining <= 0) {\n      if (maxTimeoutId) {\n        clearTimeout(maxTimeoutId);\n      }\n      var isCalled = trailingCall;\n      maxTimeoutId = timeoutId = trailingCall = undefined;\n      if (isCalled) {\n        lastCalled = util.now();\n        result = func.apply(thisArg, args);\n        if (!timeoutId && !maxTimeoutId) {\n          args = thisArg = null;\n        }\n      }\n    } else {\n      timeoutId = setTimeout(delayed, remaining);\n    }\n  };\n\n  var maxDelayed = function() {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n    maxTimeoutId = timeoutId = trailingCall = undefined;\n    if (trailing || (maxWait !== wait)) {\n      lastCalled = util.now();\n      result = func.apply(thisArg, args);\n      if (!timeoutId && !maxTimeoutId) {\n        args = thisArg = null;\n      }\n    }\n  };\n\n  return function() {\n    args = arguments;\n    stamp = util.now();\n    thisArg = this;\n    trailingCall = trailing && (timeoutId || !leading);\n\n    if (maxWait === false) {\n      var leadingCall = leading && !timeoutId;\n    } else {\n      if (!maxTimeoutId && !leading) {\n        lastCalled = stamp;\n      }\n      var remaining = maxWait - (stamp - lastCalled),\n          isCalled = remaining <= 0;\n\n      if (isCalled) {\n        if (maxTimeoutId) {\n          maxTimeoutId = clearTimeout(maxTimeoutId);\n        }\n        lastCalled = stamp;\n        result = func.apply(thisArg, args);\n      }\n      else if (!maxTimeoutId) {\n        maxTimeoutId = setTimeout(maxDelayed, remaining);\n      }\n    }\n    if (isCalled && timeoutId) {\n      timeoutId = clearTimeout(timeoutId);\n    }\n    else if (!timeoutId && wait !== maxWait) {\n      timeoutId = setTimeout(delayed, wait);\n    }\n    if (leadingCall) {\n      isCalled = true;\n      result = func.apply(thisArg, args);\n    }\n    if (isCalled && !timeoutId && !maxTimeoutId) {\n      args = thisArg = null;\n    }\n    return result;\n  };\n};\n\nmodule.exports = util;\n","module.exports = ( typeof window === 'undefined' ? null : window );\n"],"sourceRoot":"/source/"}